diff --git a/.gitignore b/.gitignore index 0e71421ee7..5be11c71ff 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ .idea/ *.iml *.iws +out/ # Mac .DS_Store @@ -27,6 +28,9 @@ log/ target/ +# Gradle +.gradle/ + spring-openid/src/main/resources/application.properties .recommenders/ /spring-hibernate4/nbproject/ @@ -66,3 +70,12 @@ 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/ +/report-*.json +transaction.log \ No newline at end of file diff --git a/JGit/pom.xml b/JGit/pom.xml index 176d55d321..deae1e45e3 100644 --- a/JGit/pom.xml +++ b/JGit/pom.xml @@ -5,9 +5,9 @@ com.baeldung JGit 1.0-SNAPSHOT + JGit jar http://maven.apache.org - JGit com.baeldung diff --git a/README.md b/README.md index f3fe5e3bf0..1030cbb09c 100644 --- a/README.md +++ b/README.md @@ -14,23 +14,28 @@ Java and Spring Tutorials ================ This project is **a collection of small and focused tutorials** - each covering a single and well defined area of development in the Java ecosystem. -A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Securiyt. +A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Security. In additional to Spring, the following technologies are in focus: `core Java`, `Jackson`, `HttpClient`, `Guava`. Building the project ==================== -To do the full build, do: `mvn install -Pdefault -Dgib.enabled=false` +To do the full build, do: `mvn clean install` Building a single module ==================== -To build a specific module run the command: `mvn clean install -Dgib.enabled=false` in the module directory +To build a specific module run the command: `mvn clean install` in the module directory Running a Spring Boot module ==================== -To run a Spring Boot module run the command: `mvn spring-boot:run -Dgib.enabled=false` in the module directory +To run a Spring Boot module run the command: `mvn spring-boot:run` in the module directory + +#Running Tests + +The command `mvn clean install` will run the unit tests in a module. +To run the integration tests, use the command `mvn clean install -Pintegration-lite-first` diff --git a/Twitter4J/pom.xml b/Twitter4J/pom.xml index 982c1adc23..b82b9f6778 100644 --- a/Twitter4J/pom.xml +++ b/Twitter4J/pom.xml @@ -2,8 +2,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 Twitter4J - jar Twitter4J + jar com.baeldung diff --git a/akka-http/README.md b/akka-http/README.md new file mode 100644 index 0000000000..3831b5079f --- /dev/null +++ b/akka-http/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http) diff --git a/akka-http/pom.xml b/akka-http/pom.xml new file mode 100644 index 0000000000..6d73f2f2e6 --- /dev/null +++ b/akka-http/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + akka-http + akka-http + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + + com.typesafe.akka + akka-http_2.12 + ${akka.http.version} + + + com.typesafe.akka + akka-stream_2.12 + ${akka.stream.version} + + + com.typesafe.akka + akka-http-jackson_2.12 + ${akka.http.version} + + + com.typesafe.akka + akka-http-testkit_2.12 + ${akka.http.version} + test + + + + + UTF-8 + UTF-8 + 10.0.11 + 2.5.11 + + diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/User.java b/akka-http/src/main/java/com/baeldung/akkahttp/User.java new file mode 100644 index 0000000000..43c21eca62 --- /dev/null +++ b/akka-http/src/main/java/com/baeldung/akkahttp/User.java @@ -0,0 +1,26 @@ +package com.baeldung.akkahttp; + +public class User { + + private final Long id; + + private final String name; + + public User() { + this.name = ""; + this.id = null; + } + + public User(Long id, String name) { + this.name = name; + this.id = id; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } +} \ No newline at end of file diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java new file mode 100644 index 0000000000..431014a88b --- /dev/null +++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java @@ -0,0 +1,41 @@ +package com.baeldung.akkahttp; + +import akka.actor.AbstractActor; +import akka.actor.Props; +import akka.japi.pf.FI; +import com.baeldung.akkahttp.UserMessages.ActionPerformed; +import com.baeldung.akkahttp.UserMessages.CreateUserMessage; +import com.baeldung.akkahttp.UserMessages.GetUserMessage; + + +class UserActor extends AbstractActor { + + private UserService userService = new UserService(); + + static Props props() { + return Props.create(UserActor.class); + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(CreateUserMessage.class, handleCreateUser()) + .match(GetUserMessage.class, handleGetUser()) + .build(); + } + + private FI.UnitApply handleCreateUser() { + return createUserMessageMessage -> { + userService.createUser(createUserMessageMessage.getUser()); + sender().tell(new ActionPerformed(String.format("User %s created.", createUserMessageMessage.getUser() + .getName())), getSelf()); + }; + } + + private FI.UnitApply handleGetUser() { + return getUserMessageMessage -> { + sender().tell(userService.getUser(getUserMessageMessage.getUserId()), getSelf()); + }; + } + +} diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java new file mode 100644 index 0000000000..995b92bcb0 --- /dev/null +++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java @@ -0,0 +1,49 @@ +package com.baeldung.akkahttp; + +import java.io.Serializable; + +public interface UserMessages { + + class ActionPerformed implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String description; + + public ActionPerformed(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + } + + class CreateUserMessage implements Serializable { + + private static final long serialVersionUID = 1L; + private final User user; + + public CreateUserMessage(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + } + + class GetUserMessage implements Serializable { + private static final long serialVersionUID = 1L; + private final Long userId; + + public GetUserMessage(Long userId) { + this.userId = userId; + } + + public Long getUserId() { + return userId; + } + } + +} diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java new file mode 100644 index 0000000000..0c1dbd1f60 --- /dev/null +++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java @@ -0,0 +1,70 @@ +package com.baeldung.akkahttp; + +import java.util.Optional; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.http.javadsl.marshallers.jackson.Jackson; +import akka.http.javadsl.model.StatusCodes; +import akka.http.javadsl.server.HttpApp; +import akka.http.javadsl.server.Route; +import akka.pattern.PatternsCS; +import akka.util.Timeout; +import com.baeldung.akkahttp.UserMessages.ActionPerformed; +import com.baeldung.akkahttp.UserMessages.CreateUserMessage; +import com.baeldung.akkahttp.UserMessages.GetUserMessage; +import scala.concurrent.duration.Duration; +import static akka.http.javadsl.server.PathMatchers.*; + +class UserServer extends HttpApp { + + private final ActorRef userActor; + + Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS)); + + UserServer(ActorRef userActor) { + this.userActor = userActor; + } + + @Override + public Route routes() { + return path("users", this::postUser) + .orElse(path(segment("users").slash(longSegment()), id -> + route(getUser(id)))); + } + + private Route getUser(Long id) { + return get(() -> { + CompletionStage> user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout) + .thenApply(obj -> (Optional) obj); + + return onSuccess(() -> user, performed -> { + if (performed.isPresent()) + return complete(StatusCodes.OK, performed.get(), Jackson.marshaller()); + else + return complete(StatusCodes.NOT_FOUND); + }); + }); + } + + private Route postUser() { + return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> { + CompletionStage userCreated = PatternsCS.ask(userActor, new CreateUserMessage(user), timeout) + .thenApply(obj -> (ActionPerformed) obj); + + return onSuccess(() -> userCreated, performed -> { + return complete(StatusCodes.CREATED, performed, Jackson.marshaller()); + }); + }))); + } + + public static void main(String[] args) throws Exception { + ActorSystem system = ActorSystem.create("userServer"); + ActorRef userActor = system.actorOf(UserActor.props(), "userActor"); + UserServer server = new UserServer(userActor); + server.startServer("localhost", 8080, system); + } + +} diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java new file mode 100644 index 0000000000..50dc1e1b28 --- /dev/null +++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java @@ -0,0 +1,35 @@ +package com.baeldung.akkahttp; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class UserService { + + private final static List users = new ArrayList<>(); + + static { + users.add(new User(1l, "Alice")); + users.add(new User(2l, "Bob")); + users.add(new User(3l, "Chris")); + users.add(new User(4l, "Dick")); + users.add(new User(5l, "Eve")); + users.add(new User(6l, "Finn")); + } + + public Optional getUser(Long id) { + return users.stream() + .filter(user -> user.getId() + .equals(id)) + .findFirst(); + } + + public void createUser(User user) { + users.add(user); + } + + public List getUsers(){ + return users; + } + +} diff --git a/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java new file mode 100644 index 0000000000..1170a2d761 --- /dev/null +++ b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.akkahttp; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.http.javadsl.model.ContentTypes; +import akka.http.javadsl.model.HttpEntities; +import akka.http.javadsl.model.HttpRequest; +import akka.http.javadsl.testkit.JUnitRouteTest; +import akka.http.javadsl.testkit.TestRoute; +import org.junit.Test; + +public class UserServerUnitTest extends JUnitRouteTest { + + ActorSystem system = ActorSystem.create("helloAkkaHttpServer"); + + ActorRef userActorRef = system.actorOf(UserActor.props(), "userActor"); + + TestRoute appRoute = testRoute(new UserServer(userActorRef).routes()); + + @Test + public void whenRequest_thenActorResponds() { + + appRoute.run(HttpRequest.GET("/users/1")) + .assertEntity(alice()) + .assertStatusCode(200); + + appRoute.run(HttpRequest.GET("/users/42")) + .assertStatusCode(404); + + appRoute.run(HttpRequest.DELETE("/users/1")) + .assertStatusCode(200); + + appRoute.run(HttpRequest.DELETE("/users/42")) + .assertStatusCode(200); + + appRoute.run(HttpRequest.POST("/users") + .withEntity(HttpEntities.create(ContentTypes.APPLICATION_JSON, zaphod()))) + .assertStatusCode(201); + + } + + private String alice() { + return "{\"id\":1,\"name\":\"Alice\"}"; + } + + private String zaphod() { + return "{\"id\":42,\"name\":\"Zaphod\"}"; + } + +} diff --git a/akka-streams/pom.xml b/akka-streams/pom.xml index a885753ce2..7719bb7351 100644 --- a/akka-streams/pom.xml +++ b/akka-streams/pom.xml @@ -14,18 +14,19 @@ com.typesafe.akka - akka-stream_2.11 + akka-stream_${scala.version} ${akkastreams.version} com.typesafe.akka - akka-stream-testkit_2.11 + akka-stream-testkit_${scala.version} ${akkastreams.version} 2.5.2 + 2.11 \ No newline at end of file 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/README.md b/algorithms-miscellaneous-1/README.md index a04874c4d2..479c2792f6 100644 --- a/algorithms-miscellaneous-1/README.md +++ b/algorithms-miscellaneous-1/README.md @@ -10,4 +10,9 @@ - [Multi-Swarm Optimization Algorithm in Java](http://www.baeldung.com/java-multi-swarm-algorithm) - [String Search Algorithms for Large Texts](http://www.baeldung.com/java-full-text-search-algorithms) - [Check If a String Contains All The Letters of The Alphabet](https://www.baeldung.com/java-string-contains-all-letters) -- [Find the Middle Element of a Linked List](http://www.baeldung.com/java-linked-list-middle-element) \ No newline at end of file +- [Find the Middle Element of a Linked List](http://www.baeldung.com/java-linked-list-middle-element) +- [Calculate Factorial in Java](https://www.baeldung.com/java-calculate-factorial) +- [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings) +- [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters) +- [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations) +- [Generate Combinations in Java](https://www.baeldung.com/java-combinations-algorithm) diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index 5006670dd9..affa66f147 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 + ${combinatoricslib3.version} + @@ -74,11 +79,11 @@ - 1.16.12 3.6.1 3.9.0 1.11 - 25.1-jre + 27.0.1-jre + 3.3.0 \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java new file mode 100644 index 0000000000..7fedd78ffb --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java @@ -0,0 +1,123 @@ +package com.baeldung.algorithms.permutation; + +import java.util.Arrays; +import java.util.Collections; + +public class Permutation { + + public static void printAllRecursive(T[] elements, char delimiter) { + printAllRecursive(elements.length, elements, delimiter); + } + + public static void printAllRecursive(int n, T[] elements, char delimiter) { + + if(n == 1) { + printArray(elements, delimiter); + } else { + for(int i = 0; i < n-1; i++) { + printAllRecursive(n - 1, elements, delimiter); + if(n % 2 == 0) { + swap(elements, i, n-1); + } else { + swap(elements, 0, n-1); + } + } + printAllRecursive(n - 1, elements, delimiter); + } + } + + public static void printAllIterative(int n, T[] elements, char delimiter) { + + int[] indexes = new int[n]; + for (int i = 0; i < n; i++) { + indexes[i] = 0; + } + + printArray(elements, delimiter); + + int i = 0; + while (i < n) { + if (indexes[i] < i) { + swap(elements, i % 2 == 0 ? 0: indexes[i], i); + printArray(elements, delimiter); + indexes[i]++; + i = 0; + } + else { + indexes[i] = 0; + i++; + } + } + } + + public static > void printAllOrdered(T[] elements, char delimiter) { + + Arrays.sort(elements); + boolean hasNext = true; + + while(hasNext) { + printArray(elements, delimiter); + int k = 0, l = 0; + hasNext = false; + for (int i = elements.length - 1; i > 0; i--) { + if (elements[i].compareTo(elements[i - 1]) > 0) { + k = i - 1; + hasNext = true; + break; + } + } + + for (int i = elements.length - 1; i > k; i--) { + if (elements[i].compareTo(elements[k]) > 0) { + l = i; + break; + } + } + + swap(elements, k, l); + Collections.reverse(Arrays.asList(elements).subList(k + 1, elements.length)); + } + } + + public static void printRandom(T[] elements, char delimiter) { + + Collections.shuffle(Arrays.asList(elements)); + printArray(elements, delimiter); + } + + private static void swap(T[] elements, int a, int b) { + + T tmp = elements[a]; + elements[a] = elements[b]; + elements[b] = tmp; + } + + private static void printArray(T[] elements, char delimiter) { + + String delimiterSpace = delimiter + " "; + for(int i = 0; i < elements.length; i++) { + System.out.print(elements[i] + delimiterSpace); + } + System.out.print('\n'); + } + + public static void main(String[] argv) { + + Integer[] elements = {1,2,3,4}; + + System.out.println("Rec:"); + printAllRecursive(elements, ';'); + + System.out.println("Iter:"); + printAllIterative(elements.length, elements, ';'); + + System.out.println("Orderes:"); + printAllOrdered(elements, ';'); + + System.out.println("Random:"); + printRandom(elements, ';'); + + System.out.println("Random:"); + printRandom(elements, ';'); + } +} diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md index d693a44f66..462644dddb 100644 --- a/algorithms-miscellaneous-2/README.md +++ b/algorithms-miscellaneous-2/README.md @@ -8,9 +8,6 @@ - [Create a Sudoku Solver in Java](http://www.baeldung.com/java-sudoku) - [Displaying Money Amounts in Words](http://www.baeldung.com/java-money-into-words) - [A Collaborative Filtering Recommendation System in Java](http://www.baeldung.com/java-collaborative-filtering-recommendations) -- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic) -- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity) -- [An Introduction to the Theory of Big-O Notation](http://www.baeldung.com/big-o-notation) - [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap) - [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points) - [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines) @@ -18,3 +15,5 @@ - [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage) - [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings) - [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude) +- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree) +- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers) diff --git a/algorithms-miscellaneous-2/pom.xml b/algorithms-miscellaneous-2/pom.xml index 5461f4ebe1..e85dd456a3 100644 --- a/algorithms-miscellaneous-2/pom.xml +++ b/algorithms-miscellaneous-2/pom.xml @@ -68,7 +68,7 @@ org.codehaus.mojo cobertura-maven-plugin - 2.7 + ${cobertura-maven-plugin.version} @@ -84,13 +84,13 @@ - 1.16.12 3.6.1 1.0.1 1.0.1 1.0.1 3.9.0 1.11 + 2.7 \ No newline at end of file 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/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..a6ec2277e5 --- /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 leftChild, TreeNode rightChild) { + 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..162119d390 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java @@ -0,0 +1,53 @@ +package com.baeldung.algorithms.reversingtree; + +import java.util.LinkedList; + +public class TreeReverser { + + 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/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(); + } +} 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..44fac57361 --- /dev/null +++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java @@ -0,0 +1,47 @@ +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 = 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 = createBinaryTree(); + + reverser.reverseIterative(treeNode); + + assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode) + .trim()); + } + + private TreeNode createBinaryTree() { + + TreeNode leaf1 = new TreeNode(1); + TreeNode leaf2 = new TreeNode(3); + TreeNode leaf3 = new TreeNode(6); + TreeNode leaf4 = new TreeNode(9); + + TreeNode nodeRight = new TreeNode(7, leaf3, leaf4); + TreeNode nodeLeft = new TreeNode(2, leaf1, leaf2); + + TreeNode root = new TreeNode(4, nodeLeft, nodeRight); + + return root; + } +} diff --git a/algorithms-miscellaneous-2/src/test/resources/graph.png b/algorithms-miscellaneous-2/src/test/resources/graph.png index 56995b8dd9..7165a51782 100644 Binary files a/algorithms-miscellaneous-2/src/test/resources/graph.png and b/algorithms-miscellaneous-2/src/test/resources/graph.png differ diff --git a/algorithms-miscellaneous-3/.gitignore b/algorithms-miscellaneous-3/.gitignore new file mode 100644 index 0000000000..30b2b7442c --- /dev/null +++ b/algorithms-miscellaneous-3/.gitignore @@ -0,0 +1,4 @@ +/target/ +.settings/ +.classpath +.project \ No newline at end of file diff --git a/algorithms-miscellaneous-3/README.md b/algorithms-miscellaneous-3/README.md new file mode 100644 index 0000000000..71541cd2b3 --- /dev/null +++ b/algorithms-miscellaneous-3/README.md @@ -0,0 +1,9 @@ +## Relevant articles: + +- [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique) +- [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine) +- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic) +- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity) +- [Checking If a List Is Sorted in Java](https://www.baeldung.com/java-check-if-list-sorted) +- [Checking if a Java Graph has a Cycle](https://www.baeldung.com/java-graph-has-a-cycle) +- [A Guide to the Folding Technique](https://www.baeldung.com/folding-hashing-technique) diff --git a/algorithms-miscellaneous-3/pom.xml b/algorithms-miscellaneous-3/pom.xml new file mode 100644 index 0000000000..3cebdd09ac --- /dev/null +++ b/algorithms-miscellaneous-3/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + algorithms-miscellaneous-3 + 0.0.1-SNAPSHOT + algorithms-miscellaneous-3 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.assertj + assertj-core + ${org.assertj.core.version} + test + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + + com.google.guava + guava + ${guava.version} + + + + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + + + + + 3.9.0 + 4.3 + 28.0-jre + + \ No newline at end of file diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java new file mode 100644 index 0000000000..796932728b --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java @@ -0,0 +1,34 @@ +package com.baeldung.algorithms.checksortedlist; + +public class Employee { + + long id; + + String name; + + public Employee() { + } + + public Employee(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/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java new file mode 100644 index 0000000000..ab6eb6bc14 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java @@ -0,0 +1,87 @@ +package com.baeldung.algorithms.checksortedlist; + +import static org.apache.commons.collections4.CollectionUtils.isEmpty; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import com.google.common.collect.Comparators; +import com.google.common.collect.Ordering;; + +public class SortedListChecker { + + private SortedListChecker() { + throw new AssertionError(); + } + + public static boolean checkIfSortedUsingIterativeApproach(List listOfStrings) { + if (isEmpty(listOfStrings) || listOfStrings.size() == 1) { + return true; + } + + Iterator iter = listOfStrings.iterator(); + String current, previous = iter.next(); + while (iter.hasNext()) { + current = iter.next(); + if (previous.compareTo(current) > 0) { + return false; + } + previous = current; + } + return true; + } + + public static boolean checkIfSortedUsingIterativeApproach(List employees, Comparator employeeComparator) { + if (isEmpty(employees) || employees.size() == 1) { + return true; + } + + Iterator iter = employees.iterator(); + Employee current, previous = iter.next(); + while (iter.hasNext()) { + current = iter.next(); + if (employeeComparator.compare(previous, current) > 0) { + return false; + } + previous = current; + } + return true; + } + + public static boolean checkIfSortedUsingRecursion(List listOfStrings) { + return isSortedRecursive(listOfStrings, listOfStrings.size()); + } + + public static boolean isSortedRecursive(List listOfStrings, int index) { + if (index < 2) { + return true; + } else if (listOfStrings.get(index - 2) + .compareTo(listOfStrings.get(index - 1)) > 0) { + return false; + } else { + return isSortedRecursive(listOfStrings, index - 1); + } + } + + public static boolean checkIfSortedUsingOrderingClass(List listOfStrings) { + return Ordering. natural() + .isOrdered(listOfStrings); + } + + public static boolean checkIfSortedUsingOrderingClass(List employees, Comparator employeeComparator) { + return Ordering.from(employeeComparator) + .isOrdered(employees); + } + + public static boolean checkIfSortedUsingOrderingClassHandlingNull(List listOfStrings) { + return Ordering. natural() + .nullsLast() + .isOrdered(listOfStrings); + } + + public static boolean checkIfSortedUsingComparators(List listOfStrings) { + return Comparators.isInOrder(listOfStrings, Comparator. naturalOrder()); + } + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java new file mode 100644 index 0000000000..5153c2e18e --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java @@ -0,0 +1,46 @@ +package com.baeldung.algorithms.enumstatemachine; + +public enum LeaveRequestState { + + Submitted { + @Override + public LeaveRequestState nextState() { + System.out.println("Starting the Leave Request and sending to Team Leader for approval."); + return Escalated; + } + + @Override + public String responsiblePerson() { + return "Employee"; + } + }, + Escalated { + @Override + public LeaveRequestState nextState() { + System.out.println("Reviewing the Leave Request and escalating to Department Manager."); + return Approved; + } + + @Override + public String responsiblePerson() { + return "Team Leader"; + } + }, + Approved { + @Override + public LeaveRequestState nextState() { + System.out.println("Approving the Leave Request."); + return this; + } + + @Override + public String responsiblePerson() { + return "Department Manager"; + } + }; + + public abstract String responsiblePerson(); + + public abstract LeaveRequestState nextState(); + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java new file mode 100644 index 0000000000..c77173b288 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java @@ -0,0 +1,51 @@ +package com.baeldung.algorithms.graphcycledetection.domain; + +import java.util.ArrayList; +import java.util.List; + +public class Graph { + + private List vertices; + + public Graph() { + this.vertices = new ArrayList<>(); + } + + public Graph(List vertices) { + this.vertices = vertices; + } + + public void addVertex(Vertex vertex) { + this.vertices.add(vertex); + } + + public void addEdge(Vertex from, Vertex to) { + from.addNeighbour(to); + } + + public boolean hasCycle() { + for (Vertex vertex : vertices) { + if (!vertex.isVisited() && hasCycle(vertex)) { + return true; + } + } + return false; + } + + public boolean hasCycle(Vertex sourceVertex) { + sourceVertex.setBeingVisited(true); + + for (Vertex neighbour : sourceVertex.getAdjacencyList()) { + if (neighbour.isBeingVisited()) { + // backward edge exists + return true; + } else if (!neighbour.isVisited() && hasCycle(neighbour)) { + return true; + } + } + + sourceVertex.setBeingVisited(false); + sourceVertex.setVisited(true); + return false; + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java new file mode 100644 index 0000000000..398cdf0d9c --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java @@ -0,0 +1,56 @@ +package com.baeldung.algorithms.graphcycledetection.domain; + +import java.util.ArrayList; +import java.util.List; + +public class Vertex { + + private String label; + + private boolean visited; + + private boolean beingVisited; + + private List adjacencyList; + + public Vertex(String label) { + this.label = label; + this.adjacencyList = new ArrayList<>(); + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public boolean isVisited() { + return visited; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + public boolean isBeingVisited() { + return beingVisited; + } + + public void setBeingVisited(boolean beingVisited) { + this.beingVisited = beingVisited; + } + + public List getAdjacencyList() { + return adjacencyList; + } + + public void setAdjacencyList(List adjacencyList) { + this.adjacencyList = adjacencyList; + } + + public void addNeighbour(Vertex adjacent) { + this.adjacencyList.add(adjacent); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java rename to algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java rename to algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java new file mode 100644 index 0000000000..a7031f4fba --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java @@ -0,0 +1,16 @@ +package com.baeldung.algorithms.twopointertechnique; + +public class LinkedListFindMiddle { + + public T findMiddle(MyNode head) { + MyNode slowPointer = head; + MyNode fastPointer = head; + + while (fastPointer.next != null && fastPointer.next.next != null) { + fastPointer = fastPointer.next.next; + slowPointer = slowPointer.next; + } + return slowPointer.data; + } + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java new file mode 100644 index 0000000000..7d93f03ef9 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java @@ -0,0 +1,20 @@ +package com.baeldung.algorithms.twopointertechnique; + +public class MyNode { + MyNode next; + E data; + + public MyNode(E value) { + data = value; + next = null; + } + + public MyNode(E value, MyNode n) { + data = value; + next = n; + } + + public void setNext(MyNode n) { + next = n; + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java new file mode 100644 index 0000000000..b4e3698c01 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java @@ -0,0 +1,22 @@ +package com.baeldung.algorithms.twopointertechnique; + +public class RotateArray { + + public void rotate(int[] input, int step) { + step %= input.length; + reverse(input, 0, input.length - 1); + reverse(input, 0, step - 1); + reverse(input, step, input.length - 1); + } + + private void reverse(int[] input, int start, int end) { + while (start < end) { + int temp = input[start]; + input[start] = input[end]; + input[end] = temp; + start++; + end--; + } + } + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java new file mode 100644 index 0000000000..14eceaa1bd --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java @@ -0,0 +1,38 @@ +package com.baeldung.algorithms.twopointertechnique; + +public class TwoSum { + + public boolean twoSum(int[] input, int targetValue) { + + int pointerOne = 0; + int pointerTwo = input.length - 1; + + while (pointerOne < pointerTwo) { + int sum = input[pointerOne] + input[pointerTwo]; + + if (sum == targetValue) { + return true; + } else if (sum < targetValue) { + pointerOne++; + } else { + pointerTwo--; + } + } + + return false; + } + + public boolean twoSumSlow(int[] input, int targetValue) { + + for (int i = 0; i < input.length; i++) { + for (int j = 1; j < input.length; j++) { + if (input[i] + input[j] == targetValue) { + return true; + } + } + } + + return false; + } + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java new file mode 100644 index 0000000000..0ea128c1d9 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java @@ -0,0 +1,78 @@ +package com.baeldung.folding; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Calculate a hash value for the strings using the folding technique. + * + * The implementation serves only to the illustration purposes and is far + * from being the most efficient. + * + * @author A.Shcherbakov + * + */ +public class FoldingHash { + + /** + * Calculate the hash value of a given string. + * + * @param str Assume it is not null + * @param groupSize the group size in the folding technique + * @param maxValue defines a max value that the hash may acquire (exclusive) + * @return integer value from 0 (inclusive) to maxValue (exclusive) + */ + public int hash(String str, int groupSize, int maxValue) { + final int[] codes = this.toAsciiCodes(str); + return IntStream.range(0, str.length()) + .filter(i -> i % groupSize == 0) + .mapToObj(i -> extract(codes, i, groupSize)) + .map(block -> concatenate(block)) + .reduce(0, (a, b) -> (a + b) % maxValue); + } + + /** + * Returns a new array of given length whose elements are take from + * the original one starting from the offset. + * + * If the original array has not enough elements, the returning array will contain + * element from the offset till the end of the original array. + * + * @param numbers original array. Assume it is not null. + * @param offset index of the element to start from. Assume it is less than the size of the array + * @param length max size of the resulting array + * @return + */ + public int[] extract(int[] numbers, int offset, int length) { + final int defect = numbers.length - (offset + length); + final int s = defect < 0 ? length + defect : length; + int[] result = new int[s]; + for (int index = 0; index < s; index++) { + result[index] = numbers[index + offset]; + } + return result; + } + + /** + * Concatenate the numbers into a single number as if they were strings. + * Assume that the procedure does not suffer from the overflow. + * @param numbers integers to concatenate + * @return + */ + public int concatenate(int[] numbers) { + final String merged = IntStream.of(numbers) + .mapToObj(number -> "" + number) + .collect(Collectors.joining()); + return Integer.parseInt(merged, 10); + } + + /** + * Convert the string into its characters' ASCII codes. + * @param str input string + * @return + */ + private int[] toAsciiCodes(String str) { + return str.chars() + .toArray(); + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java new file mode 100644 index 0000000000..3b055a0dbe --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java @@ -0,0 +1,17 @@ +package com.baeldung.folding; + +/** + * Code snippet for article "A Guide to the Folding Technique". + * + * @author A.Shcherbakov + * + */ +public class Main { + + public static void main(String... arg) { + FoldingHash hasher = new FoldingHash(); + final String str = "Java language"; + System.out.println(hasher.hash(str, 2, 100_000)); + System.out.println(hasher.hash(str, 3, 1_000)); + } +} diff --git a/core-java-10/src/main/resources/logback.xml b/algorithms-miscellaneous-3/src/main/resources/logback.xml similarity index 100% rename from core-java-10/src/main/resources/logback.xml rename to algorithms-miscellaneous-3/src/main/resources/logback.xml diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java similarity index 100% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java rename to algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java new file mode 100644 index 0000000000..44c4388e6c --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java @@ -0,0 +1,106 @@ +package com.baeldung.algorithms.checksortedlist; + +import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingComparators; +import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingIterativeApproach; +import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingOrderingClass; +import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingRecursion; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class SortedListCheckerUnitTest { + + private List sortedListOfString; + private List unsortedListOfString; + private List singletonList; + + private List employeesSortedByName; + private List employeesNotSortedByName; + + @Before + public void setUp() { + sortedListOfString = asList("Canada", "HK", "LA", "NJ", "NY"); + unsortedListOfString = asList("LA", "HK", "NJ", "NY", "Canada"); + singletonList = Collections.singletonList("NY"); + + employeesSortedByName = asList(new Employee(1L, "John"), new Employee(2L, "Kevin"), new Employee(3L, "Mike")); + employeesNotSortedByName = asList(new Employee(1L, "Kevin"), new Employee(2L, "John"), new Employee(3L, "Mike")); + } + + @Test + public void givenSortedList_whenUsingIterativeApproach_thenReturnTrue() { + assertThat(checkIfSortedUsingIterativeApproach(sortedListOfString)).isTrue(); + } + + @Test + public void givenSingleElementList_whenUsingIterativeApproach_thenReturnTrue() { + assertThat(checkIfSortedUsingIterativeApproach(singletonList)).isTrue(); + } + + @Test + public void givenUnsortedList_whenUsingIterativeApproach_thenReturnFalse() { + assertThat(checkIfSortedUsingIterativeApproach(unsortedListOfString)).isFalse(); + } + + @Test + public void givenSortedListOfEmployees_whenUsingIterativeApproach_thenReturnTrue() { + assertThat(checkIfSortedUsingIterativeApproach(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue(); + } + + @Test + public void givenUnsortedListOfEmployees_whenUsingIterativeApproach_thenReturnFalse() { + assertThat(checkIfSortedUsingIterativeApproach(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse(); + } + + @Test + public void givenSortedList_whenUsingRecursion_thenReturnTrue() { + assertThat(checkIfSortedUsingRecursion(sortedListOfString)).isTrue(); + } + + @Test + public void givenSingleElementList_whenUsingRecursion_thenReturnTrue() { + assertThat(checkIfSortedUsingRecursion(singletonList)).isTrue(); + } + + @Test + public void givenUnsortedList_whenUsingRecursion_thenReturnFalse() { + assertThat(checkIfSortedUsingRecursion(unsortedListOfString)).isFalse(); + } + + @Test + public void givenSortedList_whenUsingGuavaOrdering_thenReturnTrue() { + assertThat(checkIfSortedUsingOrderingClass(sortedListOfString)).isTrue(); + } + + @Test + public void givenUnsortedList_whenUsingGuavaOrdering_thenReturnFalse() { + assertThat(checkIfSortedUsingOrderingClass(unsortedListOfString)).isFalse(); + } + + @Test + public void givenSortedListOfEmployees_whenUsingGuavaOrdering_thenReturnTrue() { + assertThat(checkIfSortedUsingOrderingClass(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue(); + } + + @Test + public void givenUnsortedListOfEmployees_whenUsingGuavaOrdering_thenReturnFalse() { + assertThat(checkIfSortedUsingOrderingClass(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse(); + } + + @Test + public void givenSortedList_whenUsingGuavaComparators_thenReturnTrue() { + assertThat(checkIfSortedUsingComparators(sortedListOfString)).isTrue(); + } + + @Test + public void givenUnsortedList_whenUsingGuavaComparators_thenReturnFalse() { + assertThat(checkIfSortedUsingComparators(unsortedListOfString)).isFalse(); + } + +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java new file mode 100644 index 0000000000..61ed6b3aec --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.algorithms.enumstatemachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class LeaveRequestStateUnitTest { + + @Test + public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() { + LeaveRequestState state = LeaveRequestState.Escalated; + + assertEquals(state.responsiblePerson(), "Team Leader"); + } + + + @Test + public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() { + LeaveRequestState state = LeaveRequestState.Approved; + + assertEquals(state.responsiblePerson(), "Department Manager"); + } + + @Test + public void givenLeaveRequest_whenNextStateIsCalled_thenStateIsChanged() { + LeaveRequestState state = LeaveRequestState.Submitted; + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Escalated); + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Approved); + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Approved); + } +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java new file mode 100644 index 0000000000..8d464d7b97 --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.algorithms.graphcycledetection; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.baeldung.algorithms.graphcycledetection.domain.Graph; +import com.baeldung.algorithms.graphcycledetection.domain.Vertex; + +public class GraphCycleDetectionUnitTest { + + @Test + public void givenGraph_whenCycleExists_thenReturnTrue() { + + Vertex vertexA = new Vertex("A"); + Vertex vertexB = new Vertex("B"); + Vertex vertexC = new Vertex("C"); + Vertex vertexD = new Vertex("D"); + + Graph graph = new Graph(); + graph.addVertex(vertexA); + graph.addVertex(vertexB); + graph.addVertex(vertexC); + graph.addVertex(vertexD); + + graph.addEdge(vertexA, vertexB); + graph.addEdge(vertexB, vertexC); + graph.addEdge(vertexC, vertexA); + graph.addEdge(vertexD, vertexC); + + assertTrue(graph.hasCycle()); + } + + @Test + public void givenGraph_whenNoCycleExists_thenReturnFalse() { + + Vertex vertexA = new Vertex("A"); + Vertex vertexB = new Vertex("B"); + Vertex vertexC = new Vertex("C"); + Vertex vertexD = new Vertex("D"); + + Graph graph = new Graph(); + graph.addVertex(vertexA); + graph.addVertex(vertexB); + graph.addVertex(vertexC); + graph.addVertex(vertexD); + + graph.addEdge(vertexA, vertexB); + graph.addEdge(vertexB, vertexC); + graph.addEdge(vertexA, vertexC); + graph.addEdge(vertexD, vertexC); + + assertFalse(graph.hasCycle()); + } +} diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java similarity index 100% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java rename to algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java new file mode 100644 index 0000000000..422a53fa3e --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.algorithms.twopointertechnique; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class LinkedListFindMiddleUnitTest { + + LinkedListFindMiddle linkedListFindMiddle = new LinkedListFindMiddle(); + + @Test + public void givenLinkedListOfMyNodes_whenLinkedListFindMiddle_thenCorrect() { + + MyNode head = createNodesList(8); + + assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("4"); + + head = createNodesList(9); + + assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("5"); + } + + private static MyNode createNodesList(int n) { + + MyNode head = new MyNode("1"); + MyNode current = head; + + for (int i = 2; i <= n; i++) { + MyNode newNode = new MyNode(String.valueOf(i)); + current.setNext(newNode); + current = newNode; + } + + return head; + } + +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java new file mode 100644 index 0000000000..da227ae751 --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.algorithms.twopointertechnique; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class RotateArrayUnitTest { + + private RotateArray rotateArray = new RotateArray(); + + private int[] inputArray; + + private int step; + + @Test + public void givenAnArrayOfIntegers_whenRotateKsteps_thenCorrect() { + + inputArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + step = 4; + + rotateArray.rotate(inputArray, step); + + assertThat(inputArray).containsExactly(new int[] { 4, 5, 6, 7, 1, 2, 3 }); + } + +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java new file mode 100644 index 0000000000..aa76f8e1cf --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.algorithms.twopointertechnique; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class TwoSumUnitTest { + + private TwoSum twoSum = new TwoSum(); + + private int[] sortedArray; + + private int targetValue; + + @Test + public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairExists() { + + sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + + targetValue = 12; + + assertTrue(twoSum.twoSumSlow(sortedArray, targetValue)); + } + + @Test + public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairDoesNotExists() { + + sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + + targetValue = 20; + + assertFalse(twoSum.twoSumSlow(sortedArray, targetValue)); + } + + @Test + public void givenASortedArrayOfIntegers_whenTwoSum_thenPairExists() { + + sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + + targetValue = 12; + + assertTrue(twoSum.twoSum(sortedArray, targetValue)); + } + + @Test + public void givenASortedArrayOfIntegers_whenTwoSum_thenPairDoesNotExists() { + + sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + + targetValue = 20; + + assertFalse(twoSum.twoSum(sortedArray, targetValue)); + } + +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java new file mode 100644 index 0000000000..43e33d8378 --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.folding; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class FoldingHashUnitTest { + + @Test + public void givenStringJavaLanguage_whenSize2Capacity100000_then48933() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int value = hasher.hash("Java language", 2, 100_000); + assertEquals(value, 48933); + } + + @Test + public void givenStringVaJaLanguage_whenSize2Capacity100000_thenSameAsJavaLanguage() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int java = hasher.hash("Java language", 2, 100_000); + final int vaja = hasher.hash("vaJa language", 2, 100_000); + assertTrue(java == vaja); + } + + @Test + public void givenSingleElementArray_whenOffset0Size2_thenSingleElement() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 5 }, 0, 2); + assertArrayEquals(new int[] { 5 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset0Size3_thenFirstThreeElements() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 0, 3); + assertArrayEquals(new int[] { 1, 2, 3 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset1Size2_thenTwoElements() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 1, 2); + assertArrayEquals(new int[] { 2, 3 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset2SizeTooBig_thenElementsToTheEnd() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 2, 2000); + assertArrayEquals(new int[] { 3, 4, 5 }, value); + } + +} 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/animal-sniffer-mvn-plugin/pom.xml b/animal-sniffer-mvn-plugin/pom.xml index cdfb1fb2a3..55e37e2ec4 100644 --- a/animal-sniffer-mvn-plugin/pom.xml +++ b/animal-sniffer-mvn-plugin/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung animal-sniffer-mvn-plugin - jar 1.0-SNAPSHOT animal-sniffer-mvn-plugin + jar http://maven.apache.org diff --git a/annotations/pom.xml b/annotations/pom.xml index 6d83f5b057..5fe89adf0a 100644 --- a/annotations/pom.xml +++ b/annotations/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 annotations - pom annotations + pom parent-modules diff --git a/antlr/pom.xml b/antlr/pom.xml index ac66891598..91b939a882 100644 --- a/antlr/pom.xml +++ b/antlr/pom.xml @@ -10,6 +10,14 @@ 1.0.0-SNAPSHOT + + + org.antlr + antlr4-runtime + ${antlr.version} + + + @@ -44,13 +52,7 @@ - - - org.antlr - antlr4-runtime - ${antlr.version} - - + 4.7.1 3.0.0 diff --git a/apache-avro/pom.xml b/apache-avro/pom.xml index 18f9c34d64..e6fb4d24ff 100644 --- a/apache-avro/pom.xml +++ b/apache-avro/pom.xml @@ -7,14 +7,6 @@ 0.0.1-SNAPSHOT apache-avro - - UTF-8 - 3.5 - 1.8.2 - 1.8 - 1.7.25 - - com.baeldung parent-modules @@ -25,7 +17,7 @@ junit junit - 4.10 + ${junit.version} test @@ -85,4 +77,12 @@ + + + UTF-8 + 3.5 + 1.8.2 + 1.7.25 + + diff --git a/apache-curator/pom.xml b/apache-curator/pom.xml index bcca38b199..259319d547 100644 --- a/apache-curator/pom.xml +++ b/apache-curator/pom.xml @@ -3,8 +3,8 @@ 4.0.0 apache-curator 0.0.1-SNAPSHOT - jar apache-curator + jar com.baeldung @@ -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.4 3.6.1 1.7.0 diff --git a/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml b/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml index c7acf22c32..be2138e172 100644 --- a/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml +++ b/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml @@ -12,9 +12,18 @@ 0.0.1-SNAPSHOT - - 3.2.0 - + + + org.apache.cxf + cxf-rt-rs-client + ${cxf-version} + + + org.apache.cxf + cxf-rt-rs-sse + ${cxf-version} + + @@ -45,17 +54,8 @@ - - - org.apache.cxf - cxf-rt-rs-client - ${cxf-version} - - - org.apache.cxf - cxf-rt-rs-sse - ${cxf-version} - - + + 3.2.0 + diff --git a/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml b/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml index eeb5726ee1..43bbcf1ef4 100644 --- a/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml +++ b/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml @@ -13,11 +13,28 @@ 0.0.1-SNAPSHOT - - 2.4.2 - false - 18.0.0.2 - + + + + javax.ws.rs + javax.ws.rs-api + 2.1 + provided + + + javax.enterprise + cdi-api + 2.0 + provided + + + javax.json.bind + javax.json.bind-api + 1.0 + provided + + + ${project.artifactId} @@ -59,27 +76,10 @@ - - - - javax.ws.rs - javax.ws.rs-api - 2.1 - provided - - - javax.enterprise - cdi-api - 2.0 - provided - - - javax.json.bind - javax.json.bind-api - 1.0 - provided - - - + + 2.4.2 + false + 18.0.0.2 + 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) - diff --git a/apache-geode/pom.xml b/apache-geode/pom.xml index 738accdcb8..15c7e04d29 100644 --- a/apache-geode/pom.xml +++ b/apache-geode/pom.xml @@ -12,22 +12,6 @@ parent-modules 1.0.0-SNAPSHOT - - - 1.6.0 - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - @@ -38,8 +22,24 @@ junit junit - RELEASE + ${junit.version} + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + + 1.6.0 + \ No newline at end of file diff --git a/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java b/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java similarity index 98% rename from apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java rename to apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java index b96d2c9b6a..359568db98 100644 --- a/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java +++ b/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java @@ -21,7 +21,7 @@ import java.util.stream.Stream; import static org.junit.Assert.assertEquals; -public class GeodeSamplesIntegrationTest { +public class GeodeSamplesLiveTest { ClientCache cache = null; Region region = null; diff --git a/apache-meecrowave/pom.xml b/apache-meecrowave/pom.xml index cf13aa1c1b..4eb1094f94 100644 --- a/apache-meecrowave/pom.xml +++ b/apache-meecrowave/pom.xml @@ -6,52 +6,64 @@ 0.0.1 apache-meecrowave A sample REST API application with Meecrowave + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - 1.8 - 1.8 - org.apache.meecrowave meecrowave-core - 1.2.1 + ${meecrowave-core.version} org.apache.meecrowave meecrowave-jpa - 1.2.1 + ${meecrowave-jpa.version} com.squareup.okhttp3 okhttp - 3.10.0 + ${okhttp.version} org.apache.meecrowave meecrowave-junit - 1.2.0 + ${meecrowave-junit.version} test junit junit - 4.10 + ${junit.version} test - + org.apache.meecrowave meecrowave-maven-plugin - 1.2.1 + ${meecrowave-maven-plugin.version} + + + 1.8 + 1.8 + 1.2.0 + 3.10.0 + 1.2.1 + 1.2.1 + 1.2.1 + \ No newline at end of file diff --git a/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java similarity index 96% rename from apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java rename to apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java index 0dc9773490..f9a06fd7b9 100644 --- a/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java +++ b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java @@ -17,7 +17,7 @@ import okhttp3.Request; import okhttp3.Response; @RunWith(MonoMeecrowave.Runner.class) -public class ArticleEndpointsTest { +public class ArticleEndpointsUnitTest { @ConfigurationInject private Meecrowave.Builder config; diff --git a/apache-olingo/README.md b/apache-olingo/README.md new file mode 100644 index 0000000000..bfbdc97700 --- /dev/null +++ b/apache-olingo/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [OData Protocol Guide](https://www.baeldung.com/odata) diff --git a/apache-olingo/Samples.md b/apache-olingo/Samples.md new file mode 100644 index 0000000000..def8971d64 --- /dev/null +++ b/apache-olingo/Samples.md @@ -0,0 +1,21 @@ +## OData test URLs + +This following table contains test URLs that can be used with the Olingo V2 demo project. + +| URL | Description | +|------------------------------------------|-------------------------------------------------| +| `http://localhost:8180/odata/$metadata` | fetch OData metadata document | +| `http://localhost:8180/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 | +| `http://localhost:8180/odata/CarMakers?$count` | Return total count of entities in this set | +| `http://localhost:8180/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' | +| `http://localhost:8180/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' | +| `http://localhost:8180/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker| +| `http://localhost:8180/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties | +| `http://localhost:8180/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties | +| `http://localhost:8180/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation| + + + + + + diff --git a/apache-olingo/olingo2/.gitignore b/apache-olingo/olingo2/.gitignore new file mode 100644 index 0000000000..153c9335eb --- /dev/null +++ b/apache-olingo/olingo2/.gitignore @@ -0,0 +1,29 @@ +HELP.md +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +/build/ + +### VS Code ### +.vscode/ diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/olingo2/pom.xml new file mode 100644 index 0000000000..320f56b717 --- /dev/null +++ b/apache-olingo/olingo2/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + org.baeldung.examples.olingo2 + olingo2-sample + 0.0.1-SNAPSHOT + olingo2-sample + Sample Olingo 2 Project + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-jersey + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.apache.olingo + olingo-odata2-core + ${olingo2.version} + + + + javax.ws.rs + javax.ws.rs-api + + + + + org.apache.olingo + olingo-odata2-jpa-processor-core + ${olingo2.version} + + + org.apache.olingo + olingo-odata2-jpa-processor-ref + ${olingo2.version} + + + org.eclipse.persistence + eclipselink + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 1.8 + 2.0.11 + + + diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java new file mode 100644 index 0000000000..65a0428154 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java @@ -0,0 +1,298 @@ +package org.baeldung.examples.olingo2; + +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import javax.persistence.Persistence; +import javax.persistence.Query; +import javax.persistence.StoredProcedureQuery; +import javax.persistence.SynchronizationType; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.metamodel.Metamodel; +import javax.servlet.http.HttpServletRequest; + +import org.apache.olingo.odata2.api.processor.ODataContext; +import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext; +import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory; +import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; +import org.baeldung.examples.olingo2.JerseyConfig.EntityManagerFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.orm.jpa.EntityManagerFactoryUtils; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.stereotype.Component; + +/** + * ODataJPAServiceFactory implementation for our sample domain + * @author Philippe + * + */ +@Component +public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { + + private static final Logger log = LoggerFactory.getLogger(CarsODataJPAServiceFactory.class); + + public CarsODataJPAServiceFactory() { + // Enable detailed error messages (useful for debugging) + setDetailErrors(true); + } + + /** + * This method will be called by Olingo on every request to + * initialize the ODataJPAContext that will be used. + */ + @Override + public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException { + + log.info("[I32] >>> initializeODataJPAContext()"); + ODataJPAContext ctx = getODataJPAContext(); + ODataContext octx = ctx.getODataContext(); + HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT); + EntityManager em = (EntityManager)request.getAttribute(EntityManagerFilter.EM_REQUEST_ATTRIBUTE); + + // Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig) + ctx.setEntityManager(new EntityManagerWrapper(em)); + ctx.setPersistenceUnitName("default"); + + // We're managing the EM's lifecycle, so we must inform Olingo that it should not + // try to manage transactions and/or persistence sessions + ctx.setContainerManaged(true); + return ctx; + } + + static class EntityManagerWrapper implements EntityManager { + + private EntityManager delegate; + + public void persist(Object entity) { + log.info("[I68] persist: entity.class=" + entity.getClass() + .getSimpleName()); + delegate.persist(entity); + // delegate.flush(); + } + + public T merge(T entity) { + log.info("[I74] merge: entity.class=" + entity.getClass() + .getSimpleName()); + return delegate.merge(entity); + } + + public void remove(Object entity) { + log.info("[I78] remove: entity.class=" + entity.getClass() + .getSimpleName()); + delegate.remove(entity); + } + + public T find(Class entityClass, Object primaryKey) { + return delegate.find(entityClass, primaryKey); + } + + public T find(Class entityClass, Object primaryKey, Map properties) { + return delegate.find(entityClass, primaryKey, properties); + } + + public T find(Class entityClass, Object primaryKey, LockModeType lockMode) { + return delegate.find(entityClass, primaryKey, lockMode); + } + + public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) { + return delegate.find(entityClass, primaryKey, lockMode, properties); + } + + public T getReference(Class entityClass, Object primaryKey) { + return delegate.getReference(entityClass, primaryKey); + } + + public void flush() { + delegate.flush(); + } + + public void setFlushMode(FlushModeType flushMode) { + delegate.setFlushMode(flushMode); + } + + public FlushModeType getFlushMode() { + return delegate.getFlushMode(); + } + + public void lock(Object entity, LockModeType lockMode) { + delegate.lock(entity, lockMode); + } + + public void lock(Object entity, LockModeType lockMode, Map properties) { + delegate.lock(entity, lockMode, properties); + } + + public void refresh(Object entity) { + delegate.refresh(entity); + } + + public void refresh(Object entity, Map properties) { + delegate.refresh(entity, properties); + } + + public void refresh(Object entity, LockModeType lockMode) { + delegate.refresh(entity, lockMode); + } + + public void refresh(Object entity, LockModeType lockMode, Map properties) { + delegate.refresh(entity, lockMode, properties); + } + + public void clear() { + delegate.clear(); + } + + public void detach(Object entity) { + delegate.detach(entity); + } + + public boolean contains(Object entity) { + return delegate.contains(entity); + } + + public LockModeType getLockMode(Object entity) { + return delegate.getLockMode(entity); + } + + public void setProperty(String propertyName, Object value) { + delegate.setProperty(propertyName, value); + } + + public Map getProperties() { + return delegate.getProperties(); + } + + public Query createQuery(String qlString) { + return delegate.createQuery(qlString); + } + + public TypedQuery createQuery(CriteriaQuery criteriaQuery) { + return delegate.createQuery(criteriaQuery); + } + + public Query createQuery(CriteriaUpdate updateQuery) { + return delegate.createQuery(updateQuery); + } + + public Query createQuery(CriteriaDelete deleteQuery) { + return delegate.createQuery(deleteQuery); + } + + public TypedQuery createQuery(String qlString, Class resultClass) { + return delegate.createQuery(qlString, resultClass); + } + + public Query createNamedQuery(String name) { + return delegate.createNamedQuery(name); + } + + public TypedQuery createNamedQuery(String name, Class resultClass) { + return delegate.createNamedQuery(name, resultClass); + } + + public Query createNativeQuery(String sqlString) { + return delegate.createNativeQuery(sqlString); + } + + public Query createNativeQuery(String sqlString, Class resultClass) { + return delegate.createNativeQuery(sqlString, resultClass); + } + + public Query createNativeQuery(String sqlString, String resultSetMapping) { + return delegate.createNativeQuery(sqlString, resultSetMapping); + } + + public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { + return delegate.createNamedStoredProcedureQuery(name); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { + return delegate.createStoredProcedureQuery(procedureName); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { + return delegate.createStoredProcedureQuery(procedureName, resultClasses); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { + return delegate.createStoredProcedureQuery(procedureName, resultSetMappings); + } + + public void joinTransaction() { + delegate.joinTransaction(); + } + + public boolean isJoinedToTransaction() { + return delegate.isJoinedToTransaction(); + } + + public T unwrap(Class cls) { + return delegate.unwrap(cls); + } + + public Object getDelegate() { + return delegate.getDelegate(); + } + + public void close() { + log.info("[I229] close"); + delegate.close(); + } + + public boolean isOpen() { + boolean isOpen = delegate.isOpen(); + log.info("[I236] isOpen: " + isOpen); + return isOpen; + } + + public EntityTransaction getTransaction() { + log.info("[I240] getTransaction()"); + return delegate.getTransaction(); + } + + public EntityManagerFactory getEntityManagerFactory() { + return delegate.getEntityManagerFactory(); + } + + public CriteriaBuilder getCriteriaBuilder() { + return delegate.getCriteriaBuilder(); + } + + public Metamodel getMetamodel() { + return delegate.getMetamodel(); + } + + public EntityGraph createEntityGraph(Class rootType) { + return delegate.createEntityGraph(rootType); + } + + public EntityGraph createEntityGraph(String graphName) { + return delegate.createEntityGraph(graphName); + } + + public EntityGraph getEntityGraph(String graphName) { + return delegate.getEntityGraph(graphName); + } + + public List> getEntityGraphs(Class entityClass) { + return delegate.getEntityGraphs(entityClass); + } + + public EntityManagerWrapper(EntityManager delegate) { + this.delegate = delegate; + } + + } + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java new file mode 100644 index 0000000000..78caf99861 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java @@ -0,0 +1,125 @@ + package org.baeldung.examples.olingo2; + +import java.io.IOException; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.Path; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.Context; +import javax.ws.rs.ext.Provider; + +import org.apache.olingo.odata2.api.ODataServiceFactory; +import org.apache.olingo.odata2.core.rest.ODataRootLocator; +import org.apache.olingo.odata2.core.rest.app.ODataApplication; +import org.glassfish.jersey.server.ResourceConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Jersey JAX-RS configuration + * @author Philippe + * + */ +@Component +@ApplicationPath("/odata") +public class JerseyConfig extends ResourceConfig { + + + public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) { + + ODataApplication app = new ODataApplication(); + + app + .getClasses() + .forEach( c -> { + // Avoid using the default RootLocator, as we want + // a Spring Managed one + if ( !ODataRootLocator.class.isAssignableFrom(c)) { + register(c); + } + }); + + register(new CarsRootLocator(serviceFactory)); + register( new EntityManagerFilter(emf)); + } + + /** + * This filter handles the EntityManager transaction lifecycle. + * @author Philippe + * + */ + @Provider + public static class EntityManagerFilter implements ContainerRequestFilter, ContainerResponseFilter { + + private static final Logger log = LoggerFactory.getLogger(EntityManagerFilter.class); + public static final String EM_REQUEST_ATTRIBUTE = EntityManagerFilter.class.getName() + "_ENTITY_MANAGER"; + + private final EntityManagerFactory emf; + + @Context + private HttpServletRequest httpRequest; + + public EntityManagerFilter(EntityManagerFactory emf) { + this.emf = emf; + } + + @Override + public void filter(ContainerRequestContext ctx) throws IOException { + log.info("[I60] >>> filter"); + EntityManager em = this.emf.createEntityManager(); + httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em); + + // Start a new transaction unless we have a simple GET + if (!"GET".equalsIgnoreCase(ctx.getMethod())) { + em.getTransaction() + .begin(); + } + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { + + log.info("[I68] <<< filter"); + EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE); + + if (!"GET".equalsIgnoreCase(requestContext.getMethod())) { + EntityTransaction t = em.getTransaction(); + if (t.isActive()) { + if (!t.getRollbackOnly()) { + t.commit(); + } + } + } + + em.close(); + + } + + } + + @Path("/") + public static class CarsRootLocator extends ODataRootLocator { + + private CarsODataJPAServiceFactory serviceFactory; + + public CarsRootLocator(CarsODataJPAServiceFactory serviceFactory) { + this.serviceFactory = serviceFactory; + } + + @Override + public ODataServiceFactory getServiceFactory() { + return this.serviceFactory; + } + + } + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java new file mode 100644 index 0000000000..fa58612088 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java @@ -0,0 +1,14 @@ +package org.baeldung.examples.olingo2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class Olingo2SampleApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(Olingo2SampleApplication.class); + } +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java new file mode 100644 index 0000000000..e66d266062 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java @@ -0,0 +1,115 @@ +package org.baeldung.examples.olingo2.domain; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +@Entity +@Table(name = "car_maker") +public class CarMaker { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "name") + private String name; + + @OneToMany(mappedBy = "maker", orphanRemoval = true, cascade = CascadeType.ALL) + private List models; + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the models + */ + public List getModels() { + return models; + } + + /** + * @param models the models to set + */ + public void setModels(List models) { + this.models = models; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((models == null) ? 0 : models.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarMaker other = (CarMaker) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (models == null) { + if (other.models != null) + return false; + } else if (!models.equals(other.models)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java new file mode 100644 index 0000000000..f9f563e01e --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java @@ -0,0 +1,159 @@ +package org.baeldung.examples.olingo2.domain; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +@Entity +@Table(name = "car_model") +public class CarModel { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @NotNull + private String name; + + @NotNull + private Integer year; + + @NotNull + private String sku; + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "maker_fk") + private CarMaker maker; + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the year + */ + public Integer getYear() { + return year; + } + + /** + * @param year the year to set + */ + public void setYear(Integer year) { + this.year = year; + } + + /** + * @return the sku + */ + public String getSku() { + return sku; + } + + /** + * @param sku the sku to set + */ + public void setSku(String sku) { + this.sku = sku; + } + + /** + * @return the maker + */ + public CarMaker getMaker() { + return maker; + } + + /** + * @param maker the maker to set + */ + public void setMaker(CarMaker maker) { + this.maker = maker; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((maker == null) ? 0 : maker.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((sku == null) ? 0 : sku.hashCode()); + result = prime * result + ((year == null) ? 0 : year.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarModel other = (CarModel) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (maker == null) { + if (other.maker != null) + return false; + } else if (!maker.equals(other.maker)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (sku == null) { + if (other.sku != null) + return false; + } else if (!sku.equals(other.sku)) + return false; + if (year == null) { + if (other.year != null) + return false; + } else if (!year.equals(other.year)) + return false; + return true; + } + +} diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/olingo2/src/main/resources/application.yml new file mode 100644 index 0000000000..71df0c4166 --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -0,0 +1,12 @@ +server: + port: 8080 + +spring: + jersey: + application-path: /odata + + jpa: + show-sql: true + open-in-view: false + hibernate: + ddl-auto: update \ No newline at end of file diff --git a/apache-olingo/olingo2/src/main/resources/data.sql b/apache-olingo/olingo2/src/main/resources/data.sql new file mode 100644 index 0000000000..327f2688c5 --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/data.sql @@ -0,0 +1,12 @@ +insert into car_maker(id,name) values (1,'Special Motors'); +insert into car_maker(id,name) values (2,'BWM'); +insert into car_maker(id,name) values (3,'Dolores'); + +insert into car_model(id,maker_fk,name,sku,year) values(1,1,'Muze','SM001',2018); +insert into car_model(id,maker_fk,name,sku,year) values(2,1,'Empada','SM002',2008); + +insert into car_model(id,maker_fk,name,sku,year) values(4,2,'BWM-100','BWM100',2008); +insert into car_model(id,maker_fk,name,sku,year) values(5,2,'BWM-200','BWM200',2009); +insert into car_model(id,maker_fk,name,sku,year) values(6,2,'BWM-300','BWM300',2008); + +alter sequence hibernate_sequence restart with 100; \ No newline at end of file diff --git a/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java new file mode 100644 index 0000000000..687f6ab1ff --- /dev/null +++ b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java @@ -0,0 +1,16 @@ +package org.baeldung.examples.olingo2; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class Olingo2SampleApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/apache-olingo/olingo2/src/test/resources/olingo2-queries.json b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json new file mode 100644 index 0000000000..9fdade6d10 --- /dev/null +++ b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json @@ -0,0 +1,256 @@ +{ + "info": { + "_postman_id": "afa8e1e5-ab0e-4f1d-8b99-b7d1f091f975", + "name": "OLingo2 - Cars", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "GET Metadata", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/$metadata" + }, + "response": [] + }, + { + "name": "GET All CarMakers", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarMakers" + }, + "response": [] + }, + { + "name": "GET Makers with Pagination", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$top=1&$orderby=Name&$skip=3", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$top", + "value": "1" + }, + { + "key": "$orderby", + "value": "Name" + }, + { + "key": "$skip", + "value": "3" + } + ] + } + }, + "response": [] + }, + { + "name": "GET Makers and Models", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$expand=CarModelDetails", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$expand", + "value": "CarModelDetails" + } + ] + } + }, + "response": [] + }, + { + "name": "GET Makers with filter", + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$filter=Name eq 'BWM'&$expand=CarModelDetails", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$filter", + "value": "Name eq 'BWM'" + }, + { + "key": "$expand", + "value": "CarModelDetails" + } + ] + } + }, + "response": [] + }, + { + "name": "Create CarMaker", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/atom+xml", + "type": "text" + }, + { + "key": "Accept", + "value": "application/atom+xml", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n Lucien\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarMakers" + }, + "response": [] + }, + { + "name": "Create CarModel", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\t Tata\r\n\t TT101\r\n\t 2018\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarModels" + }, + "response": [] + }, + { + "name": "Update CarMaker", + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n 5\r\n KaiserWagen\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarMakers(5L)" + }, + "response": [] + }, + { + "name": "All CarModels", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarModels" + }, + "response": [] + }, + { + "name": "Delete CarModel", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarModels(100L)" + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/apache-pulsar/pom.xml b/apache-pulsar/pom.xml index a4c09586eb..11df6d0b87 100644 --- a/apache-pulsar/pom.xml +++ b/apache-pulsar/pom.xml @@ -11,12 +11,14 @@ org.apache.pulsar pulsar-client - 2.1.1-incubating + ${pulsar-client.version} compile + 1.8 1.8 + 2.1.1-incubating diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml index 9a807c2f26..1227fdca46 100644 --- a/apache-solrj/pom.xml +++ b/apache-solrj/pom.xml @@ -4,8 +4,8 @@ com.baeldung apache-solrj 0.0.1-SNAPSHOT - jar apache-solrj + jar com.baeldung diff --git a/apache-spark/README.md b/apache-spark/README.md index fb8059eb27..a4dce212b4 100644 --- a/apache-spark/README.md +++ b/apache-spark/README.md @@ -1,3 +1,4 @@ ### Relevant articles - [Introduction to Apache Spark](http://www.baeldung.com/apache-spark) +- [Building a Data Pipeline with Kafka, Spark Streaming and Cassandra](https://www.baeldung.com/kafka-spark-data-pipeline) diff --git a/apache-spark/pom.xml b/apache-spark/pom.xml index 290b63a14d..b8c1962dd4 100644 --- a/apache-spark/pom.xml +++ b/apache-spark/pom.xml @@ -4,8 +4,8 @@ com.baeldung apache-spark 1.0-SNAPSHOT - jar apache-spark + jar http://maven.apache.org @@ -15,16 +15,79 @@ - org.apache.spark - spark-core_2.10 + spark-core_2.11 ${org.apache.spark.spark-core.version} + provided + + org.apache.spark + spark-sql_2.11 + ${org.apache.spark.spark-sql.version} + provided + + + org.apache.spark + spark-streaming_2.11 + ${org.apache.spark.spark-streaming.version} + provided + + + org.apache.spark + spark-streaming-kafka-0-10_2.11 + ${org.apache.spark.spark-streaming-kafka.version} + + + com.datastax.spark + spark-cassandra-connector_2.11 + ${com.datastax.spark.spark-cassandra-connector.version} + + + com.datastax.spark + spark-cassandra-connector-java_2.11 + ${com.datastax.spark.spark-cassandra-connector-java.version} + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + + + + maven-assembly-plugin + + + package + + single + + + + + + jar-with-dependencies + + + + + + - 2.2.0 + 2.3.0 + 2.3.0 + 2.3.0 + 2.3.0 + 2.3.0 + 1.5.2 + 3.2 diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java new file mode 100644 index 0000000000..b0caa468b1 --- /dev/null +++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java @@ -0,0 +1,25 @@ +package com.baeldung.data.pipeline; + +import java.io.Serializable; + +public class Word implements Serializable { + private static final long serialVersionUID = 1L; + private String word; + private int count; + Word(String word, int count) { + this.word = word; + this.count = count; + } + public String getWord() { + return word; + } + public void setWord(String word) { + this.word = word; + } + public int getCount() { + return count; + } + public void setCount(int count) { + this.count = count; + } +} \ No newline at end of file diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java new file mode 100644 index 0000000000..db2a73b411 --- /dev/null +++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java @@ -0,0 +1,80 @@ +package com.baeldung.data.pipeline; + +import static com.datastax.spark.connector.japi.CassandraJavaUtil.javaFunctions; +import static com.datastax.spark.connector.japi.CassandraJavaUtil.mapToRow; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.streaming.Durations; +import org.apache.spark.streaming.api.java.JavaDStream; +import org.apache.spark.streaming.api.java.JavaInputDStream; +import org.apache.spark.streaming.api.java.JavaPairDStream; +import org.apache.spark.streaming.api.java.JavaStreamingContext; +import org.apache.spark.streaming.kafka010.ConsumerStrategies; +import org.apache.spark.streaming.kafka010.KafkaUtils; +import org.apache.spark.streaming.kafka010.LocationStrategies; + +import scala.Tuple2; + +public class WordCountingApp { + + public static void main(String[] args) throws InterruptedException { + Logger.getLogger("org") + .setLevel(Level.OFF); + Logger.getLogger("akka") + .setLevel(Level.OFF); + + Map kafkaParams = new HashMap<>(); + kafkaParams.put("bootstrap.servers", "localhost:9092"); + kafkaParams.put("key.deserializer", StringDeserializer.class); + kafkaParams.put("value.deserializer", StringDeserializer.class); + kafkaParams.put("group.id", "use_a_separate_group_id_for_each_stream"); + kafkaParams.put("auto.offset.reset", "latest"); + kafkaParams.put("enable.auto.commit", false); + + Collection topics = Arrays.asList("messages"); + + SparkConf sparkConf = new SparkConf(); + sparkConf.setMaster("local[2]"); + sparkConf.setAppName("WordCountingApp"); + sparkConf.set("spark.cassandra.connection.host", "127.0.0.1"); + + JavaStreamingContext streamingContext = new JavaStreamingContext(sparkConf, Durations.seconds(1)); + + JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams)); + + JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value())); + + JavaDStream lines = results.map(tuple2 -> tuple2._2()); + + JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+")) + .iterator()); + + JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((i1, i2) -> i1 + i2); + + wordCounts.foreachRDD(javaRdd -> { + Map wordCountMap = javaRdd.collectAsMap(); + for (String key : wordCountMap.keySet()) { + List wordList = Arrays.asList(new Word(key, wordCountMap.get(key))); + JavaRDD rdd = streamingContext.sparkContext() + .parallelize(wordList); + javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class)) + .saveToCassandra(); + } + }); + + streamingContext.start(); + streamingContext.awaitTermination(); + } +} \ No newline at end of file diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java new file mode 100644 index 0000000000..efbe5f3851 --- /dev/null +++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java @@ -0,0 +1,97 @@ +package com.baeldung.data.pipeline; + +import static com.datastax.spark.connector.japi.CassandraJavaUtil.javaFunctions; +import static com.datastax.spark.connector.japi.CassandraJavaUtil.mapToRow; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +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.Function2; +import org.apache.spark.streaming.Durations; +import org.apache.spark.streaming.StateSpec; +import org.apache.spark.streaming.api.java.JavaDStream; +import org.apache.spark.streaming.api.java.JavaInputDStream; +import org.apache.spark.streaming.api.java.JavaMapWithStateDStream; +import org.apache.spark.streaming.api.java.JavaPairDStream; +import org.apache.spark.streaming.api.java.JavaStreamingContext; +import org.apache.spark.streaming.kafka010.ConsumerStrategies; +import org.apache.spark.streaming.kafka010.KafkaUtils; +import org.apache.spark.streaming.kafka010.LocationStrategies; + +import scala.Tuple2; + +public class WordCountingAppWithCheckpoint { + + public static JavaSparkContext sparkContext; + + public static void main(String[] args) throws InterruptedException { + + Logger.getLogger("org") + .setLevel(Level.OFF); + Logger.getLogger("akka") + .setLevel(Level.OFF); + + Map kafkaParams = new HashMap<>(); + kafkaParams.put("bootstrap.servers", "localhost:9092"); + kafkaParams.put("key.deserializer", StringDeserializer.class); + kafkaParams.put("value.deserializer", StringDeserializer.class); + kafkaParams.put("group.id", "use_a_separate_group_id_for_each_stream"); + kafkaParams.put("auto.offset.reset", "latest"); + kafkaParams.put("enable.auto.commit", false); + + Collection topics = Arrays.asList("messages"); + + SparkConf sparkConf = new SparkConf(); + sparkConf.setMaster("local[2]"); + sparkConf.setAppName("WordCountingAppWithCheckpoint"); + sparkConf.set("spark.cassandra.connection.host", "127.0.0.1"); + + JavaStreamingContext streamingContext = new JavaStreamingContext(sparkConf, Durations.seconds(1)); + + sparkContext = streamingContext.sparkContext(); + + streamingContext.checkpoint("./.checkpoint"); + + JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams)); + + JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value())); + + JavaDStream lines = results.map(tuple2 -> tuple2._2()); + + JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+")) + .iterator()); + + JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((Function2) (i1, i2) -> i1 + i2); + + JavaMapWithStateDStream> cumulativeWordCounts = wordCounts.mapWithState(StateSpec.function((word, one, state) -> { + int sum = one.orElse(0) + (state.exists() ? state.get() : 0); + Tuple2 output = new Tuple2<>(word, sum); + state.update(sum); + return output; + })); + + cumulativeWordCounts.foreachRDD(javaRdd -> { + List> wordCountList = javaRdd.collect(); + for (Tuple2 tuple : wordCountList) { + List wordList = Arrays.asList(new Word(tuple._1, tuple._2)); + JavaRDD rdd = sparkContext.parallelize(wordList); + javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class)) + .saveToCassandra(); + } + }); + + streamingContext.start(); + streamingContext.awaitTermination(); + } +} \ No newline at end of file diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml index 19cf77d945..24ab0b861d 100644 --- a/apache-velocity/pom.xml +++ b/apache-velocity/pom.xml @@ -4,8 +4,8 @@ com.baeldung 0.1-SNAPSHOT apache-velocity - war apache-velocity + war com.baeldung @@ -59,7 +59,6 @@ - 1.2 4.5.2 1.7 2.0 diff --git a/autovalue/README.md b/autovalue/README.md index c6a08359ef..f33ff6899f 100644 --- a/autovalue/README.md +++ b/autovalue/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Introduction to AutoValue](http://www.baeldung.com/introduction-to-autovalue) - [Introduction to AutoFactory](http://www.baeldung.com/autofactory) +- [Google AutoService](https://www.baeldung.com/google-autoservice) diff --git a/autovalue/pom.xml b/autovalue/pom.xml index 3ec2d26b35..a10e8ef055 100644 --- a/autovalue/pom.xml +++ b/autovalue/pom.xml @@ -29,6 +29,12 @@ + + com.google.auto.service + auto-service + ${auto-service.version} + true + com.google.inject @@ -40,6 +46,7 @@ 1.3 1.0-beta5 + 1.0-rc5 4.2.0 diff --git a/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java b/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java index e0ee8879a5..65d0eb6f58 100644 --- a/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java +++ b/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java @@ -1,8 +1,9 @@ package com.baeldung.autofactory.provided; +import com.baeldung.autofactory.model.Camera; import com.google.auto.factory.AutoFactory; import com.google.auto.factory.Provided; -import javafx.scene.Camera; + import javax.inject.Provider; diff --git a/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java new file mode 100644 index 0000000000..86d42e80fa --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.autoservice; + +import com.google.auto.service.AutoService; + +import java.util.Locale; + +@AutoService(TranslationService.class) +public class BingTranslationServiceProvider implements TranslationService { + @Override + public String translate(String message, Locale from, Locale to) { + // implementation details + return message + " (translated by Bing)"; + } +} diff --git a/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java new file mode 100644 index 0000000000..0bf91ee5ec --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.autoservice; + +import com.google.auto.service.AutoService; + +import java.util.Locale; + +@AutoService(TranslationService.class) +public class GoogleTranslationServiceProvider implements TranslationService { + @Override + public String translate(String message, Locale from, Locale to) { + // implementation details + return message + " (translated by Google)"; + } +} diff --git a/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java new file mode 100644 index 0000000000..580db46cd1 --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java @@ -0,0 +1,7 @@ +package com.baeldung.autoservice; + +import java.util.Locale; + +public interface TranslationService { + String translate(String message, Locale from, Locale to); +} \ No newline at end of file diff --git a/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java new file mode 100644 index 0000000000..9e1bd6d291 --- /dev/null +++ b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.autoservice; + +import com.baeldung.autoservice.TranslationService; +import org.junit.Before; +import org.junit.Test; + +import java.util.ServiceLoader; +import java.util.stream.StreamSupport; + +import static org.junit.Assert.assertEquals; + +public class TranslationServiceUnitTest { + + private ServiceLoader loader; + + @Before + public void setUp() { + loader = ServiceLoader.load(TranslationService.class); + } + + @Test + public void whenServiceLoaderLoads_thenLoadsAllProviders() { + long count = StreamSupport.stream(loader.spliterator(), false).count(); + assertEquals(2, count); + } + + @Test + public void whenServiceLoaderLoadsGoogleService_thenGoogleIsLoaded() { + TranslationService googleService = StreamSupport.stream(loader.spliterator(), false) + .filter(p -> p.getClass().getSimpleName().equals("GoogleTranslationServiceProvider")) + .findFirst() + .get(); + + String message = "message"; + assertEquals(message + " (translated by Google)", googleService.translate(message, null, null)); + } +} \ No newline at end of file diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index c47c3cd86f..c799718e61 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -5,8 +5,8 @@ com.baeldung aws-lambda 0.1.0-SNAPSHOT - jar aws-lambda + jar parent-modules 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) diff --git a/aws/pom.xml b/aws/pom.xml index ab63f6afa1..560f9145f9 100644 --- a/aws/pom.xml +++ b/aws/pom.xml @@ -4,8 +4,8 @@ com.baeldung aws 0.1.0-SNAPSHOT - jar aws + jar com.baeldung diff --git a/axon/pom.xml b/axon/pom.xml index c643ea9e57..2b9ac1fcdd 100644 --- a/axon/pom.xml +++ b/axon/pom.xml @@ -4,29 +4,61 @@ 4.0.0 axon axon - + Basic Axon Framework with Spring Boot configuration tutorial + - parent-modules com.baeldung - 1.0.0-SNAPSHOT + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + org.axonframework + axon-spring-boot-starter + ${axon.version} + + + org.axonframework + axon-server-connector + + + + org.axonframework axon-test ${axon.version} test + - org.axonframework - axon-core - ${axon.version} + org.springframework.boot + spring-boot-autoconfigure + ${spring-boot.version} + compile + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + runtime - 3.0.2 + 4.0.3 \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/MessagesRunner.java b/axon/src/main/java/com/baeldung/axon/MessagesRunner.java deleted file mode 100644 index 77b50d09bd..0000000000 --- a/axon/src/main/java/com/baeldung/axon/MessagesRunner.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.axon; - -import com.baeldung.axon.aggregates.MessagesAggregate; -import com.baeldung.axon.commands.CreateMessageCommand; -import com.baeldung.axon.commands.MarkReadMessageCommand; -import com.baeldung.axon.eventhandlers.MessagesEventHandler; -import org.axonframework.commandhandling.AggregateAnnotationCommandHandler; -import org.axonframework.commandhandling.CommandBus; -import org.axonframework.commandhandling.SimpleCommandBus; -import org.axonframework.commandhandling.gateway.CommandGateway; -import org.axonframework.commandhandling.gateway.DefaultCommandGateway; -import org.axonframework.eventhandling.AnnotationEventListenerAdapter; -import org.axonframework.eventsourcing.EventSourcingRepository; -import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore; -import org.axonframework.eventsourcing.eventstore.EventStore; -import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine; - -import java.util.UUID; - -public class MessagesRunner { - - public static void main(String[] args) { - CommandBus commandBus = new SimpleCommandBus(); - - CommandGateway commandGateway = new DefaultCommandGateway(commandBus); - - EventStore eventStore = new EmbeddedEventStore(new InMemoryEventStorageEngine()); - - EventSourcingRepository repository = - new EventSourcingRepository<>(MessagesAggregate.class, eventStore); - - - AggregateAnnotationCommandHandler messagesAggregateAggregateAnnotationCommandHandler = - new AggregateAnnotationCommandHandler(MessagesAggregate.class, repository); - messagesAggregateAggregateAnnotationCommandHandler.subscribe(commandBus); - - final AnnotationEventListenerAdapter annotationEventListenerAdapter = - new AnnotationEventListenerAdapter(new MessagesEventHandler()); - eventStore.subscribe(eventMessages -> eventMessages.forEach(e -> { - try { - annotationEventListenerAdapter.handle(e); - } catch (Exception e1) { - throw new RuntimeException(e1); - - } - } - - )); - - final String itemId = UUID.randomUUID().toString(); - commandGateway.send(new CreateMessageCommand(itemId, "Hello, how is your day? :-)")); - commandGateway.send(new MarkReadMessageCommand(itemId)); - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/OrderApplication.java b/axon/src/main/java/com/baeldung/axon/OrderApplication.java new file mode 100644 index 0000000000..8f507e141c --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/OrderApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.axon; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class OrderApplication { + + public static void main(String[] args) { + SpringApplication.run(OrderApplication.class, args); + } + +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java b/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java deleted file mode 100644 index e762604b74..0000000000 --- a/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.axon.aggregates; - -import com.baeldung.axon.commands.CreateMessageCommand; -import com.baeldung.axon.commands.MarkReadMessageCommand; -import com.baeldung.axon.events.MessageCreatedEvent; -import com.baeldung.axon.events.MessageReadEvent; -import org.axonframework.commandhandling.CommandHandler; -import org.axonframework.commandhandling.model.AggregateIdentifier; -import org.axonframework.eventhandling.EventHandler; - -import static org.axonframework.commandhandling.model.AggregateLifecycle.apply; - - -public class MessagesAggregate { - - @AggregateIdentifier - private String id; - - public MessagesAggregate() { - } - - @CommandHandler - public MessagesAggregate(CreateMessageCommand command) { - apply(new MessageCreatedEvent(command.getId(), command.getText())); - } - - @EventHandler - public void on(MessageCreatedEvent event) { - this.id = event.getId(); - } - - @CommandHandler - public void markRead(MarkReadMessageCommand command) { - apply(new MessageReadEvent(id)); - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java b/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java new file mode 100644 index 0000000000..b37b2fdd66 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java @@ -0,0 +1,58 @@ +package com.baeldung.axon.commandmodel; + +import static org.axonframework.modelling.command.AggregateLifecycle.apply; + +import org.axonframework.commandhandling.CommandHandler; +import org.axonframework.eventsourcing.EventSourcingHandler; +import org.axonframework.modelling.command.AggregateIdentifier; +import org.axonframework.spring.stereotype.Aggregate; + +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderPlacedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; + +@Aggregate +public class OrderAggregate { + + @AggregateIdentifier + private String orderId; + private boolean orderConfirmed; + + @CommandHandler + public OrderAggregate(PlaceOrderCommand command) { + apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct())); + } + + @CommandHandler + public void handle(ConfirmOrderCommand command) { + apply(new OrderConfirmedEvent(orderId)); + } + + @CommandHandler + public void handle(ShipOrderCommand command) { + if (!orderConfirmed) { + throw new IllegalStateException("Cannot ship an order which has not been confirmed yet."); + } + + apply(new OrderShippedEvent(orderId)); + } + + @EventSourcingHandler + public void on(OrderPlacedEvent event) { + this.orderId = event.getOrderId(); + orderConfirmed = false; + } + + @EventSourcingHandler + public void on(OrderConfirmedEvent event) { + orderConfirmed = true; + } + + protected OrderAggregate() { + // Required by Axon to build a default Aggregate prior to Event Sourcing + } + +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java deleted file mode 100644 index d0651bf12e..0000000000 --- a/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.axon.commands; - - -import org.axonframework.commandhandling.TargetAggregateIdentifier; - -public class CreateMessageCommand { - - @TargetAggregateIdentifier - private final String id; - private final String text; - - public CreateMessageCommand(String id, String text) { - this.id = id; - this.text = text; - } - - public String getId() { - return id; - } - - public String getText() { - return text; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java deleted file mode 100644 index e66582d9ec..0000000000 --- a/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.axon.commands; - - -import org.axonframework.commandhandling.TargetAggregateIdentifier; - -public class MarkReadMessageCommand { - - @TargetAggregateIdentifier - private final String id; - - public MarkReadMessageCommand(String id) { - this.id = id; - } - - public String getId() { - return id; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java new file mode 100644 index 0000000000..244b69f3b7 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java @@ -0,0 +1,43 @@ +package com.baeldung.axon.coreapi.commands; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +import java.util.Objects; + +public class ConfirmOrderCommand { + + @TargetAggregateIdentifier + private final String orderId; + + public ConfirmOrderCommand(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final ConfirmOrderCommand other = (ConfirmOrderCommand) obj; + return Objects.equals(this.orderId, other.orderId); + } + + @Override + public String toString() { + return "ConfirmOrderCommand{" + + "orderId='" + orderId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java new file mode 100644 index 0000000000..c70d503050 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java @@ -0,0 +1,51 @@ +package com.baeldung.axon.coreapi.commands; + +import java.util.Objects; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +public class PlaceOrderCommand { + + @TargetAggregateIdentifier + private final String orderId; + private final String product; + + public PlaceOrderCommand(String orderId, String product) { + this.orderId = orderId; + this.product = product; + } + + public String getOrderId() { + return orderId; + } + + public String getProduct() { + return product; + } + + @Override + public int hashCode() { + return Objects.hash(orderId, product); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final PlaceOrderCommand other = (PlaceOrderCommand) obj; + return Objects.equals(this.orderId, other.orderId) + && Objects.equals(this.product, other.product); + } + + @Override + public String toString() { + return "PlaceOrderCommand{" + + "orderId='" + orderId + '\'' + + ", product='" + product + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java new file mode 100644 index 0000000000..7312bc1fdb --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java @@ -0,0 +1,43 @@ +package com.baeldung.axon.coreapi.commands; + +import java.util.Objects; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +public class ShipOrderCommand { + + @TargetAggregateIdentifier + private final String orderId; + + public ShipOrderCommand(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final ShipOrderCommand other = (ShipOrderCommand) obj; + return Objects.equals(this.orderId, other.orderId); + } + + @Override + public String toString() { + return "ShipOrderCommand{" + + "orderId='" + orderId + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java new file mode 100644 index 0000000000..d2b7d58435 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java @@ -0,0 +1,40 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class OrderConfirmedEvent { + + private final String orderId; + + public OrderConfirmedEvent(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final OrderConfirmedEvent other = (OrderConfirmedEvent) obj; + return Objects.equals(this.orderId, other.orderId); + } + + @Override + public String toString() { + return "OrderConfirmedEvent{" + + "orderId='" + orderId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java new file mode 100644 index 0000000000..06de4c5f9f --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java @@ -0,0 +1,48 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class OrderPlacedEvent { + + private final String orderId; + private final String product; + + public OrderPlacedEvent(String orderId, String product) { + this.orderId = orderId; + this.product = product; + } + + public String getOrderId() { + return orderId; + } + + public String getProduct() { + return product; + } + + @Override + public int hashCode() { + return Objects.hash(orderId, product); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final OrderPlacedEvent other = (OrderPlacedEvent) obj; + return Objects.equals(this.orderId, other.orderId) + && Objects.equals(this.product, other.product); + } + + @Override + public String toString() { + return "OrderPlacedEvent{" + + "orderId='" + orderId + '\'' + + ", product='" + product + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java new file mode 100644 index 0000000000..76aa684629 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java @@ -0,0 +1,40 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class OrderShippedEvent { + + private final String orderId; + + public OrderShippedEvent(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final OrderShippedEvent other = (OrderShippedEvent) obj; + return Objects.equals(this.orderId, other.orderId); + } + + @Override + public String toString() { + return "OrderShippedEvent{" + + "orderId='" + orderId + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java new file mode 100644 index 0000000000..9d6ca2cfb2 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java @@ -0,0 +1,5 @@ +package com.baeldung.axon.coreapi.queries; + +public class FindAllOrderedProductsQuery { + +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java new file mode 100644 index 0000000000..d215c5fc32 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java @@ -0,0 +1,7 @@ +package com.baeldung.axon.coreapi.queries; + +public enum OrderStatus { + + PLACED, CONFIRMED, SHIPPED + +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java new file mode 100644 index 0000000000..d847bb2a98 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java @@ -0,0 +1,64 @@ +package com.baeldung.axon.coreapi.queries; + +import java.util.Objects; + +public class OrderedProduct { + + private final String orderId; + private final String product; + private OrderStatus orderStatus; + + public OrderedProduct(String orderId, String product) { + this.orderId = orderId; + this.product = product; + orderStatus = OrderStatus.PLACED; + } + + public String getOrderId() { + return orderId; + } + + public String getProduct() { + return product; + } + + public OrderStatus getOrderStatus() { + return orderStatus; + } + + public void setOrderConfirmed() { + this.orderStatus = OrderStatus.CONFIRMED; + } + + public void setOrderShipped() { + this.orderStatus = OrderStatus.SHIPPED; + } + + @Override + public int hashCode() { + return Objects.hash(orderId, product, orderStatus); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final OrderedProduct other = (OrderedProduct) obj; + return Objects.equals(this.orderId, other.orderId) + && Objects.equals(this.product, other.product) + && Objects.equals(this.orderStatus, other.orderStatus); + } + + @Override + public String toString() { + return "OrderedProduct{" + + "orderId='" + orderId + '\'' + + ", product='" + product + '\'' + + ", orderStatus=" + orderStatus + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java b/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java deleted file mode 100644 index 3e51e19c4e..0000000000 --- a/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.axon.eventhandlers; - -import com.baeldung.axon.events.MessageReadEvent; -import com.baeldung.axon.events.MessageCreatedEvent; -import org.axonframework.eventhandling.EventHandler; - - -public class MessagesEventHandler { - - @EventHandler - public void handle(MessageCreatedEvent event) { - System.out.println("Message received: " + event.getText() + " (" + event.getId() + ")"); - } - - @EventHandler - public void handle(MessageReadEvent event) { - System.out.println("Message read: " + event.getId()); - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java deleted file mode 100644 index 3c9aac5ed8..0000000000 --- a/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.axon.events; - -public class MessageCreatedEvent { - - private final String id; - private final String text; - - public MessageCreatedEvent(String id, String text) { - this.id = id; - this.text = text; - } - - public String getId() { - return id; - } - - public String getText() { - return text; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java deleted file mode 100644 index 57bfc8e19e..0000000000 --- a/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.axon.events; - -public class MessageReadEvent { - - private final String id; - - public MessageReadEvent(String id) { - this.id = id; - } - - public String getId() { - return id; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java new file mode 100644 index 0000000000..a9f34cc691 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java @@ -0,0 +1,52 @@ +package com.baeldung.axon.gui; + +import java.util.List; +import java.util.UUID; + +import org.axonframework.commandhandling.gateway.CommandGateway; +import org.axonframework.messaging.responsetypes.ResponseTypes; +import org.axonframework.queryhandling.QueryGateway; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; +import com.baeldung.axon.coreapi.queries.OrderedProduct; + +@RestController +public class OrderRestEndpoint { + + private final CommandGateway commandGateway; + private final QueryGateway queryGateway; + + public OrderRestEndpoint(CommandGateway commandGateway, QueryGateway queryGateway) { + this.commandGateway = commandGateway; + this.queryGateway = queryGateway; + } + + @PostMapping("/ship-order") + public void shipOrder() { + String orderId = UUID.randomUUID().toString(); + commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair")); + commandGateway.send(new ConfirmOrderCommand(orderId)); + commandGateway.send(new ShipOrderCommand(orderId)); + } + + @PostMapping("/ship-unconfirmed-order") + public void shipUnconfirmedOrder() { + String orderId = UUID.randomUUID().toString(); + commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair")); + // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet. + commandGateway.send(new ShipOrderCommand(orderId)); + } + + @GetMapping("/all-orders") + public List findAllOrderedProducts() { + return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(OrderedProduct.class)) + .join(); + } + +} diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java new file mode 100644 index 0000000000..d4cf3d999b --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java @@ -0,0 +1,50 @@ +package com.baeldung.axon.querymodel; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.axonframework.eventhandling.EventHandler; +import org.axonframework.queryhandling.QueryHandler; +import org.springframework.stereotype.Service; + +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderPlacedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; +import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; +import com.baeldung.axon.coreapi.queries.OrderedProduct; + +@Service +public class OrderedProductsEventHandler { + + private final Map orderedProducts = new HashMap<>(); + + @EventHandler + public void on(OrderPlacedEvent event) { + String orderId = event.getOrderId(); + orderedProducts.put(orderId, new OrderedProduct(orderId, event.getProduct())); + } + + @EventHandler + public void on(OrderConfirmedEvent event) { + orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> { + orderedProduct.setOrderConfirmed(); + return orderedProduct; + }); + } + + @EventHandler + public void on(OrderShippedEvent event) { + orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> { + orderedProduct.setOrderShipped(); + return orderedProduct; + }); + } + + @QueryHandler + public List handle(FindAllOrderedProductsQuery query) { + return new ArrayList<>(orderedProducts.values()); + } + +} \ No newline at end of file diff --git a/axon/src/main/resources/order-api.http b/axon/src/main/resources/order-api.http new file mode 100644 index 0000000000..a3c69c72bc --- /dev/null +++ b/axon/src/main/resources/order-api.http @@ -0,0 +1,11 @@ +POST http://localhost:8080/ship-order + +### + +POST http://localhost:8080/ship-unconfirmed-order + +### + +GET http://localhost:8080/all-orders + +### diff --git a/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java b/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java deleted file mode 100644 index ad099d2c2b..0000000000 --- a/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.axon; - -import com.baeldung.axon.aggregates.MessagesAggregate; -import com.baeldung.axon.commands.CreateMessageCommand; -import com.baeldung.axon.commands.MarkReadMessageCommand; -import com.baeldung.axon.events.MessageCreatedEvent; -import com.baeldung.axon.events.MessageReadEvent; -import org.axonframework.test.aggregate.AggregateTestFixture; -import org.axonframework.test.aggregate.FixtureConfiguration; -import org.junit.Before; -import org.junit.Test; - -import java.util.UUID; - -public class MessagesAggregateIntegrationTest { - - private FixtureConfiguration fixture; - - @Before - public void setUp() throws Exception { - fixture = new AggregateTestFixture(MessagesAggregate.class); - - } - - @Test - public void giveAggregateRoot_whenCreateMessageCommand_thenShouldProduceMessageCreatedEvent() throws Exception { - String eventText = "Hello, how is your day?"; - String id = UUID.randomUUID().toString(); - fixture.given() - .when(new CreateMessageCommand(id, eventText)) - .expectEvents(new MessageCreatedEvent(id, eventText)); - } - - @Test - public void givenMessageCreatedEvent_whenReadMessageCommand_thenShouldProduceMessageReadEvent() throws Exception { - String id = UUID.randomUUID().toString(); - - fixture.given(new MessageCreatedEvent(id, "Hello :-)")) - .when(new MarkReadMessageCommand(id)) - .expectEvents(new MessageReadEvent(id)); - } -} \ No newline at end of file diff --git a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java new file mode 100644 index 0000000000..9beedbaa19 --- /dev/null +++ b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.axon.commandmodel; + +import java.util.UUID; + +import org.axonframework.test.aggregate.AggregateTestFixture; +import org.axonframework.test.aggregate.FixtureConfiguration; +import org.junit.*; + +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderPlacedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; + +public class OrderAggregateUnitTest { + + private FixtureConfiguration fixture; + + @Before + public void setUp() { + fixture = new AggregateTestFixture<>(OrderAggregate.class); + } + + @Test + public void giveNoPriorActivity_whenPlaceOrderCommand_thenShouldPublishOrderPlacedEvent() { + String orderId = UUID.randomUUID().toString(); + String product = "Deluxe Chair"; + fixture.givenNoPriorActivity() + .when(new PlaceOrderCommand(orderId, product)) + .expectEvents(new OrderPlacedEvent(orderId, product)); + } + + @Test + public void givenOrderPlacedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() { + String orderId = UUID.randomUUID().toString(); + String product = "Deluxe Chair"; + fixture.given(new OrderPlacedEvent(orderId, product)) + .when(new ConfirmOrderCommand(orderId)) + .expectEvents(new OrderConfirmedEvent(orderId)); + } + + @Test + public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowIllegalStateException() { + String orderId = UUID.randomUUID().toString(); + String product = "Deluxe Chair"; + fixture.given(new OrderPlacedEvent(orderId, product)) + .when(new ShipOrderCommand(orderId)) + .expectException(IllegalStateException.class); + } + + @Test + public void givenOrderPlacedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() { + String orderId = UUID.randomUUID().toString(); + String product = "Deluxe Chair"; + fixture.given(new OrderPlacedEvent(orderId, product), new OrderConfirmedEvent(orderId)) + .when(new ShipOrderCommand(orderId)) + .expectEvents(new OrderShippedEvent(orderId)); + } + +} \ No newline at end of file diff --git a/azure/README.md b/azure/README.md index c60186e1ce..ae8c443660 100644 --- a/azure/README.md +++ b/azure/README.md @@ -1,4 +1,4 @@ ### Relevant Articles: -- [Deploy Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure) +- [Deploy a Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure) diff --git a/azure/pom.xml b/azure/pom.xml index 555efeef70..270b3e4829 100644 --- a/azure/pom.xml +++ b/azure/pom.xml @@ -5,9 +5,9 @@ com.baeldung azure 0.1 - war azure Demo project for Spring Boot on Azure + war parent-boot-2 @@ -127,7 +127,6 @@ ${azure.containerRegistry}.azurecr.io 1.1.0 1.1.0 - 1.8 diff --git a/blade/README.md b/blade/README.md new file mode 100644 index 0000000000..1f2a00ed3f --- /dev/null +++ b/blade/README.md @@ -0,0 +1,5 @@ +### Relevant Articles: + +- [Blade – A Complete Guidebook](http://www.baeldung.com/blade) + +Run Integration Tests with `mvn integration-test` diff --git a/blade/pom.xml b/blade/pom.xml new file mode 100644 index 0000000000..37615bed01 --- /dev/null +++ b/blade/pom.xml @@ -0,0 +1,205 @@ + + + 4.0.0 + + com.baeldung + blade + 1.0.0-SNAPSHOT + blade + + + + + + + + + + + + com.bladejava + blade-mvc + ${blade-mvc.version} + + + + org.webjars + bootstrap + ${bootstrap.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + junit + junit + ${junit.version} + test + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + test + + + org.apache.httpcomponents + httpmime + ${httpmime.version} + test + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + test + + + + sample-blade-app + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 3 + true + + **/*LiveTest.java + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + **/*LiveTest.java + + + + + + integration-test + verify + + + + + + + com.bazaarvoice.maven.plugins + process-exec-maven-plugin + ${process-exec-maven-plugin.version} + + + + blade-process + pre-integration-test + + start + + + Blade + false + + java + -jar + sample-blade-app.jar + + + + + + + stop-all + post-integration-test + + stop-all + + + + + + + + maven-assembly-plugin + 3.1.0 + + ${project.build.finalName} + false + + + com.baeldung.blade.sample.App + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + UTF-8 + + + + + + + 1.8 + 1.8 + 2.0.14.RELEASE + 4.2.1 + 3.8.1 + 1.18.4 + 4.12 + 4.5.6 + 4.5.6 + 4.4.10 + 3.11.1 + 3.0.0-M3 + 0.7 + 2.21.0 + 3.7.0 + + diff --git a/blade/src/main/java/com/baeldung/blade/sample/App.java b/blade/src/main/java/com/baeldung/blade/sample/App.java new file mode 100644 index 0000000000..f3f3d4aebd --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/App.java @@ -0,0 +1,38 @@ +package com.baeldung.blade.sample; + +import com.baeldung.blade.sample.interceptors.BaeldungMiddleware; +import com.blade.Blade; +import com.blade.event.EventType; +import com.blade.mvc.WebContext; +import com.blade.mvc.http.Session; + +public class App { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(App.class); + + public static void main(String[] args) { + + Blade.of() + .get("/", ctx -> ctx.render("index.html")) + .get("/basic-route-example", ctx -> ctx.text("GET called")) + .post("/basic-route-example", ctx -> ctx.text("POST called")) + .put("/basic-route-example", ctx -> ctx.text("PUT called")) + .delete("/basic-route-example", ctx -> ctx.text("DELETE called")) + .addStatics("/custom-static") + // .showFileList(true) + .enableCors(true) + .before("/user/*", ctx -> log.info("[NarrowedHook] Before '/user/*', URL called: " + ctx.uri())) + .on(EventType.SERVER_STARTED, e -> { + String version = WebContext.blade() + .env("app.version") + .orElse("N/D"); + log.info("[Event::serverStarted] Loading 'app.version' from configuration, value: " + version); + }) + .on(EventType.SESSION_CREATED, e -> { + Session session = (Session) e.attribute("session"); + session.attribute("mySessionValue", "Baeldung"); + }) + .use(new BaeldungMiddleware()) + .start(App.class, args); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java new file mode 100644 index 0000000000..339ba701f7 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java @@ -0,0 +1,37 @@ +package com.baeldung.blade.sample; + +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.Session; + +@Path +public class AttributesExampleController { + + public final static String REQUEST_VALUE = "Some Request value"; + public final static String SESSION_VALUE = "1337"; + public final static String HEADER = "Some Header"; + + @GetRoute("/request-attribute-example") + public void getRequestAttribute(Request request, Response response) { + request.attribute("request-val", REQUEST_VALUE); + String requestVal = request.attribute("request-val"); + response.text(requestVal); + } + + @GetRoute("/session-attribute-example") + public void getSessionAttribute(Request request, Response response) { + Session session = request.session(); + session.attribute("session-val", SESSION_VALUE); + String sessionVal = session.attribute("session-val"); + response.text(sessionVal); + } + + @GetRoute("/header-example") + public void getHeader(Request request, Response response) { + String headerVal = request.header("a-header", HEADER); + response.header("a-header", headerVal); + } + +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java new file mode 100644 index 0000000000..f0c22c70dd --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java @@ -0,0 +1,22 @@ +package com.baeldung.blade.sample; + +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.Response; + +@Path +public class LogExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleController.class); + + @Route(value = "/test-logs") + public void testLogs(Response response) { + log.trace("This is a TRACE Message"); + log.debug("This is a DEBUG Message"); + log.info("This is an INFO Message"); + log.warn("This is a WARN Message"); + log.error("This is an ERROR Message"); + response.text("Check in ./logs"); + } + +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java new file mode 100644 index 0000000000..bc28244022 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java @@ -0,0 +1,71 @@ +package com.baeldung.blade.sample; + +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; + +import com.baeldung.blade.sample.vo.User; +import com.blade.mvc.annotation.CookieParam; +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.HeaderParam; +import com.blade.mvc.annotation.JSON; +import com.blade.mvc.annotation.MultipartParam; +import com.blade.mvc.annotation.Param; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.PathParam; +import com.blade.mvc.annotation.PostRoute; +import com.blade.mvc.http.Response; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.ui.RestResponse; + +@Path +public class ParameterInjectionExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ParameterInjectionExampleController.class); + + @GetRoute("/params/form") + public void formParam(@Param String name, Response response) { + log.info("name: " + name); + response.text(name); + } + + @GetRoute("/params/path/:uid") + public void restfulParam(@PathParam Integer uid, Response response) { + log.info("uid: " + uid); + response.text(String.valueOf(uid)); + } + + @PostRoute("/params-file") // DO NOT USE A SLASH WITHIN THE ROUTE OR IT WILL BREAK (?) + @JSON + public RestResponse fileParam(@MultipartParam FileItem fileItem) throws Exception { + try { + byte[] fileContent = fileItem.getData(); + + log.debug("Saving the uploaded file"); + java.nio.file.Path tempFile = Files.createTempFile("baeldung_tempfiles", ".tmp"); + Files.write(tempFile, fileContent, StandardOpenOption.WRITE); + + return RestResponse.ok(); + } catch (Exception e) { + log.error(e.getMessage(), e); + return RestResponse.fail(e.getMessage()); + } + } + + @GetRoute("/params/header") + public void headerParam(@HeaderParam String customheader, Response response) { + log.info("Custom header: " + customheader); + response.text(customheader); + } + + @GetRoute("/params/cookie") + public void cookieParam(@CookieParam(defaultValue = "default value") String myCookie, Response response) { + log.info("myCookie: " + myCookie); + response.text(myCookie); + } + + @PostRoute("/params/vo") + public void voParam(@Param User user, Response response) { + log.info("user as voParam: " + user.toString()); + response.html(user.toString() + "

Back"); + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java new file mode 100644 index 0000000000..7ba2a270a9 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java @@ -0,0 +1,78 @@ +package com.baeldung.blade.sample; + +import com.baeldung.blade.sample.configuration.BaeldungException; +import com.blade.mvc.WebContext; +import com.blade.mvc.annotation.DeleteRoute; +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.PostRoute; +import com.blade.mvc.annotation.PutRoute; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; + +@Path +public class RouteExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteExampleController.class); + + @GetRoute("/route-example") + public String get() { + return "get.html"; + } + + @PostRoute("/route-example") + public String post() { + return "post.html"; + } + + @PutRoute("/route-example") + public String put() { + return "put.html"; + } + + @DeleteRoute("/route-example") + public String delete() { + return "delete.html"; + } + + @Route(value = "/another-route-example", method = HttpMethod.GET) + public String anotherGet() { + return "get.html"; + } + + @Route(value = "/allmatch-route-example") + public String allmatch() { + return "allmatch.html"; + } + + @Route(value = "/triggerInternalServerError") + public void triggerInternalServerError() { + int x = 1 / 0; + } + + @Route(value = "/triggerBaeldungException") + public void triggerBaeldungException() throws BaeldungException { + throw new BaeldungException("Foobar Exception to threat differently"); + } + + @Route(value = "/user/foo") + public void urlCoveredByNarrowedWebhook(Response response) { + response.text("Check out for the WebHook covering '/user/*' in the logs"); + } + + @GetRoute("/load-configuration-in-a-route") + public void loadConfigurationInARoute(Response response) { + String authors = WebContext.blade() + .env("app.authors", "Unknown authors"); + log.info("[/load-configuration-in-a-route] Loading 'app.authors' from configuration, value: " + authors); + response.render("index.html"); + } + + @GetRoute("/template-output-test") + public void templateOutputTest(Request request, Response response) { + request.attribute("name", "Blade"); + response.render("template-output-test.html"); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java new file mode 100644 index 0000000000..01a030b7e7 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java @@ -0,0 +1,9 @@ +package com.baeldung.blade.sample.configuration; + +public class BaeldungException extends RuntimeException { + + public BaeldungException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java new file mode 100644 index 0000000000..ab7b81c0dc --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java @@ -0,0 +1,25 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.ioc.annotation.Bean; +import com.blade.mvc.WebContext; +import com.blade.mvc.handler.DefaultExceptionHandler; + +@Bean +public class GlobalExceptionHandler extends DefaultExceptionHandler { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @Override + public void handle(Exception e) { + if (e instanceof BaeldungException) { + Exception baeldungException = (BaeldungException) e; + String msg = baeldungException.getMessage(); + log.error("[GlobalExceptionHandler] Intercepted an exception to threat with additional logic. Error message: " + msg); + WebContext.response() + .render("index.html"); + + } else { + super.handle(e); + } + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java new file mode 100644 index 0000000000..0f1aab1b52 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.Blade; +import com.blade.ioc.annotation.Bean; +import com.blade.loader.BladeLoader; +import com.blade.mvc.WebContext; + +@Bean +public class LoadConfig implements BladeLoader { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoadConfig.class); + + @Override + public void load(Blade blade) { + String version = WebContext.blade() + .env("app.version") + .orElse("N/D"); + String authors = WebContext.blade() + .env("app.authors", "Unknown authors"); + + log.info("[LoadConfig] loaded 'app.version' (" + version + ") and 'app.authors' (" + authors + ") in a configuration bean"); + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java new file mode 100644 index 0000000000..c170975818 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java @@ -0,0 +1,15 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.ioc.annotation.Bean; +import com.blade.task.annotation.Schedule; + +@Bean +public class ScheduleExample { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScheduleExample.class); + + @Schedule(name = "baeldungTask", cron = "0 */1 * * * ?") + public void runScheduledTask() { + log.info("[ScheduleExample] This is a scheduled Task running once per minute."); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java new file mode 100644 index 0000000000..4d0d178b0d --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java @@ -0,0 +1,17 @@ +package com.baeldung.blade.sample.interceptors; + +import com.blade.ioc.annotation.Bean; +import com.blade.mvc.RouteContext; +import com.blade.mvc.hook.WebHook; + +@Bean +public class BaeldungHook implements WebHook { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungHook.class); + + @Override + public boolean before(RouteContext ctx) { + log.info("[BaeldungHook] called before Route method"); + return true; + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java new file mode 100644 index 0000000000..3342cd8b01 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java @@ -0,0 +1,15 @@ +package com.baeldung.blade.sample.interceptors; + +import com.blade.mvc.RouteContext; +import com.blade.mvc.hook.WebHook; + +public class BaeldungMiddleware implements WebHook { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungMiddleware.class); + + @Override + public boolean before(RouteContext context) { + log.info("[BaeldungMiddleware] called before Route method and other WebHooks"); + return true; + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/vo/User.java b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java new file mode 100644 index 0000000000..b493dc3663 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java @@ -0,0 +1,16 @@ +package com.baeldung.blade.sample.vo; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import lombok.Getter; +import lombok.Setter; + +public class User { + @Getter @Setter private String name; + @Getter @Setter private String site; + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } +} \ No newline at end of file diff --git a/blade/src/main/resources/application.properties b/blade/src/main/resources/application.properties new file mode 100644 index 0000000000..ebf365406a --- /dev/null +++ b/blade/src/main/resources/application.properties @@ -0,0 +1,5 @@ +mvc.statics.show-list=true +mvc.view.404=my-404.html +mvc.view.500=my-500.html +app.version=0.0.1 +app.authors=Andrea Ligios diff --git a/blade/src/main/resources/custom-static/icon.png b/blade/src/main/resources/custom-static/icon.png new file mode 100644 index 0000000000..59af395afc Binary files /dev/null and b/blade/src/main/resources/custom-static/icon.png differ diff --git a/blade/src/main/resources/favicon.ico b/blade/src/main/resources/favicon.ico new file mode 100644 index 0000000000..ca63a6a890 Binary files /dev/null and b/blade/src/main/resources/favicon.ico differ diff --git a/blade/src/main/resources/static/app.css b/blade/src/main/resources/static/app.css new file mode 100644 index 0000000000..9fff13d9b6 --- /dev/null +++ b/blade/src/main/resources/static/app.css @@ -0,0 +1 @@ +/* App CSS */ \ No newline at end of file diff --git a/core-java-io/src/main/resources/META-INF/BenchmarkList b/blade/src/main/resources/static/app.js old mode 100755 new mode 100644 similarity index 100% rename from core-java-io/src/main/resources/META-INF/BenchmarkList rename to blade/src/main/resources/static/app.js diff --git a/blade/src/main/resources/static/file-upload.html b/blade/src/main/resources/static/file-upload.html new file mode 100644 index 0000000000..b805be81b1 --- /dev/null +++ b/blade/src/main/resources/static/file-upload.html @@ -0,0 +1,43 @@ + + + + +Title + + + + + +

File Upload and download test

+
+ + +
+ +
+ Back + + + + \ No newline at end of file diff --git a/blade/src/main/resources/static/user-post.html b/blade/src/main/resources/static/user-post.html new file mode 100644 index 0000000000..ccfc4e8d0b --- /dev/null +++ b/blade/src/main/resources/static/user-post.html @@ -0,0 +1,25 @@ + + + + +Title + + + + + +

User POJO post test

+ + +
+ Person POJO: + + + +
+ +
+ Back + + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/allmatch.html b/blade/src/main/resources/templates/allmatch.html new file mode 100644 index 0000000000..7a4bfa070f --- /dev/null +++ b/blade/src/main/resources/templates/allmatch.html @@ -0,0 +1 @@ +ALLMATCH called \ No newline at end of file diff --git a/blade/src/main/resources/templates/delete.html b/blade/src/main/resources/templates/delete.html new file mode 100644 index 0000000000..1acb4b0b62 --- /dev/null +++ b/blade/src/main/resources/templates/delete.html @@ -0,0 +1 @@ +DELETE called \ No newline at end of file diff --git a/blade/src/main/resources/templates/get.html b/blade/src/main/resources/templates/get.html new file mode 100644 index 0000000000..2c37aa1058 --- /dev/null +++ b/blade/src/main/resources/templates/get.html @@ -0,0 +1 @@ +GET called \ No newline at end of file diff --git a/blade/src/main/resources/templates/index.html b/blade/src/main/resources/templates/index.html new file mode 100644 index 0000000000..6b7c2e77ad --- /dev/null +++ b/blade/src/main/resources/templates/index.html @@ -0,0 +1,30 @@ + + + + +Baeldung Blade App • Written by Andrea Ligios + + + +

Baeldung Blade App - Showcase

+ +

Manual tests

+

The following are tests which are not covered by integration tests, but that can be run manually in order to check the functionality, either in the browser or in the logs, depending on the case.

+ + + + +

Session value created in App.java

+

mySessionValue = ${mySessionValue}

+ + + + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/my-404.html b/blade/src/main/resources/templates/my-404.html new file mode 100644 index 0000000000..0fa694f241 --- /dev/null +++ b/blade/src/main/resources/templates/my-404.html @@ -0,0 +1,10 @@ + + + + + 404 Not found + + + Custom Error 404 Page + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/my-500.html b/blade/src/main/resources/templates/my-500.html new file mode 100644 index 0000000000..cc8438bfd6 --- /dev/null +++ b/blade/src/main/resources/templates/my-500.html @@ -0,0 +1,12 @@ + + + + + 500 Internal Server Error + + +

Custom Error 500 Page

+

The following error occurred: "${message}"

+
 ${stackTrace} 
+ + \ No newline at end of file diff --git a/blade/src/main/resources/templates/post.html b/blade/src/main/resources/templates/post.html new file mode 100644 index 0000000000..b7a8a931cd --- /dev/null +++ b/blade/src/main/resources/templates/post.html @@ -0,0 +1 @@ +POST called \ No newline at end of file diff --git a/blade/src/main/resources/templates/put.html b/blade/src/main/resources/templates/put.html new file mode 100644 index 0000000000..bdbe6d3285 --- /dev/null +++ b/blade/src/main/resources/templates/put.html @@ -0,0 +1 @@ +PUT called \ No newline at end of file diff --git a/blade/src/main/resources/templates/template-output-test.html b/blade/src/main/resources/templates/template-output-test.html new file mode 100644 index 0000000000..233b12fb88 --- /dev/null +++ b/blade/src/main/resources/templates/template-output-test.html @@ -0,0 +1 @@ +

Hello, ${name}!

\ No newline at end of file diff --git a/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java new file mode 100644 index 0000000000..1172e6755f --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java @@ -0,0 +1,56 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class AppLiveTest { + + @Test + public void givenBasicRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenBasicRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called"); + } + } + + @Test + public void givenBasicRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called"); + } + } + + @Test + public void givenBasicRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called"); + } + } +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java new file mode 100644 index 0000000000..7cf00c2d4b --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java @@ -0,0 +1,55 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class AttributesExampleControllerLiveTest { + + @Test + public void givenRequestAttribute_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/request-attribute-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.REQUEST_VALUE); + } + } + + @Test + public void givenSessionAttribute_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/session-attribute-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.SESSION_VALUE); + } + } + + @Test + public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example"); + request.addHeader("a-header","foobar"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo("foobar"); + } + } + + @Test + public void givenNoHeader_whenSet_thenRetrieveDefaultValueWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo(AttributesExampleController.HEADER); + } + } + +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java new file mode 100644 index 0000000000..fbd5280116 --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java @@ -0,0 +1,82 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class ParameterInjectionExampleControllerLiveTest { + + @Test + public void givenFormParam_whenSet_thenRetrieveWithGet() throws Exception { + URIBuilder builder = new URIBuilder("http://localhost:9000/params/form"); + builder.setParameter("name", "Andrea Ligios"); + + final HttpUriRequest request = new HttpGet(builder.build()); + + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("Andrea Ligios"); + } + } + + @Test + public void givenPathParam_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/path/1337"); + + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("1337"); + } + } + + // @Test + // public void givenFileParam_whenSet_thenRetrieveWithGet() throws Exception { + // + // byte[] data = "this is some temp file content".getBytes("UTF-8"); + // java.nio.file.Path tempFile = Files.createTempFile("baeldung_test_tempfiles", ".tmp"); + // Files.write(tempFile, data, StandardOpenOption.WRITE); + // + // //HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(tempFile.toFile())).build(); + // HttpEntity entity = MultipartEntityBuilder.create().addTextBody("field1", "value1") + // .addBinaryBody("fileItem", tempFile.toFile(), ContentType.create("application/octet-stream"), "file1.txt").build(); + // + // final HttpPost post = new HttpPost("http://localhost:9000/params-file"); + // post.setEntity(entity); + // + // try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create().build().execute(post);) { + // assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("file1.txt"); + // } + // } + + @Test + public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/header"); + request.addHeader("customheader", "foobar"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("foobar"); + } + } + + @Test + public void givenNoCookie_whenCalled_thenReadDefaultValue() throws Exception { + + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/cookie"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("default value"); + } + + } + +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java new file mode 100644 index 0000000000..df8e70c461 --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java @@ -0,0 +1,117 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class RouteExampleControllerLiveTest { + + @Test + public void givenRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called"); + } + } + + @Test + public void givenRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called"); + } + } + + @Test + public void givenRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called"); + } + } + + @Test + public void givenAnotherRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/another-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenAllMatchRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenRequestAttribute_whenRenderedWithTemplate_thenCorrectlyEvaluateIt() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/template-output-test"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("

Hello, Blade!

"); + } + } + +} diff --git a/bootique/pom.xml b/bootique/pom.xml index 880b9a516f..4dd9ba4833 100644 --- a/bootique/pom.xml +++ b/bootique/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung.bootique bootique - jar 1.0-SNAPSHOT bootique + jar http://maven.apache.org @@ -65,7 +65,6 @@ com.baeldung.bootique.App 0.23 - 2.4.3 diff --git a/cas/cas-secured-app/pom.xml b/cas/cas-secured-app/pom.xml index 2291da9084..338a9e5653 100644 --- a/cas/cas-secured-app/pom.xml +++ b/cas/cas-secured-app/pom.xml @@ -3,9 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 cas-secured-app - jar cas-secured-app Demo project for CAS + jar parent-boot-1 diff --git a/cas/pom.xml b/cas/pom.xml new file mode 100644 index 0000000000..6d141277c5 --- /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/cdi/pom.xml b/cdi/pom.xml index 0cf5062ccc..c98ad57495 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -27,7 +27,7 @@ org.hamcrest hamcrest-core - ${hamcrest-core.version} + ${org.hamcrest.version} test @@ -59,13 +59,12 @@ test + 2.0.SP1 3.0.5.Final 1.9.2 - 1.3 3.10.0 - 4.12 5.1.2.RELEASE diff --git a/checker-plugin/pom.xml b/checker-plugin/pom.xml index 45f0939e77..08408366a4 100644 --- a/checker-plugin/pom.xml +++ b/checker-plugin/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung checker-plugin - jar 1.0-SNAPSHOT checker-plugin + jar http://maven.apache.org diff --git a/clojure/ring/.gitignore b/clojure/ring/.gitignore new file mode 100644 index 0000000000..d18f225992 --- /dev/null +++ b/clojure/ring/.gitignore @@ -0,0 +1,12 @@ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +.hgignore +.hg/ diff --git a/clojure/ring/README.md b/clojure/ring/README.md new file mode 100644 index 0000000000..20263c6b95 --- /dev/null +++ b/clojure/ring/README.md @@ -0,0 +1,19 @@ +# Clojure Ring Examples + +This project acts as a set of examples for the Clojure Ring library. + +## Runing the examples + +The examples can all be run from the Leiningen REPL. + +Firstly, start the REPL with `lein repl`. Then the examples can be executed with: + +* `(run simple-handler)` - A simple handler that just echos a constant string to the client +* `(run check-ip-handler)` - A handler that echos the clients IP Address back to them +* `(run echo-handler)` - A handler that echos the value of the "input" parameter back +* `(run request-count-handler)` - A handler with a session that tracks how many times this session has requested this handler + +In all cases, the handlers can be accessed on http://localhost:3000. + +## Relevant Articles +- [Writing Clojure Webapps with Ring](https://www.baeldung.com/clojure-ring) diff --git a/clojure/ring/project.clj b/clojure/ring/project.clj new file mode 100644 index 0000000000..7f2fcc4263 --- /dev/null +++ b/clojure/ring/project.clj @@ -0,0 +1,8 @@ +(defproject baeldung-ring "0.1.0-SNAPSHOT" + :dependencies [[org.clojure/clojure "1.10.0"] + [ring/ring-core "1.7.1"] + [ring/ring-jetty-adapter "1.7.1"] + [ring/ring-devel "1.7.1"]] + :plugins [[lein-ring "0.12.5"]] + :ring {:handler ring.core/simple-handler} + :repl-options {:init-ns ring.core}) diff --git a/clojure/ring/src/ring/core.clj b/clojure/ring/src/ring/core.clj new file mode 100644 index 0000000000..a56e2f2bde --- /dev/null +++ b/clojure/ring/src/ring/core.clj @@ -0,0 +1,48 @@ +(ns ring.core + (:use ring.adapter.jetty + [ring.middleware.content-type] + [ring.middleware.cookies] + [ring.middleware.params] + [ring.middleware.session] + [ring.middleware.session.cookie] + [ring.util.response])) + +;; Handler that just echos back the string "Hello World" +(defn simple-handler [request] + {:status 200 + :headers {"Content-Type" "text/plain"} + :body "Hello World"}) + +;; Handler that echos back the clients IP Address +;; This demonstrates building responses properly, and extracting values from the request +(defn check-ip-handler [request] + (content-type + (response (:remote-addr request)) + "text/plain")) + +;; Handler that echos back the incoming parameter "input" +;; This demonstrates middleware chaining and accessing parameters +(def echo-handler + (-> (fn [{params :params}] + (content-type + (response (get params "input")) + "text/plain")) + (wrap-params {:encoding "UTF-8"}) + )) + +;; Handler that keeps track of how many times each session has accessed the service +;; This demonstrates cookies and sessions +(def request-count-handler + (-> (fn [{session :session}] + (let [count (:count session 0) + session (assoc session :count (inc count))] + (-> (response (str "You accessed this page " count " times.")) + (assoc :session session)))) + wrap-cookies + (wrap-session {:cookie-attrs {:max-age 3600}}) + )) + +;; Run the provided handler on port 3000 +(defn run + [h] + (run-jetty h {:port 3000})) diff --git a/cloud-foundry-uaa/README.md b/cloud-foundry-uaa/README.md new file mode 100644 index 0000000000..b2f382cad1 --- /dev/null +++ b/cloud-foundry-uaa/README.md @@ -0,0 +1,3 @@ +### Revelant Articles + +- [A Quick Guide To Using Cloud Foundry UAA](https://www.baeldung.com/cloud-foundry-uaa) 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..ebaa99fb6c --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-config/uaa.yml @@ -0,0 +1,68 @@ +issuer: + uri: http://localhost:8080/uaa + +spring_profiles: default,hsqldb + +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..c6de00dbe9 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + com.example + cf-uaa-oauth2-client + 0.0.1-SNAPSHOT + uaa-client-webapp + Demo project for Spring Boot + + + 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-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..8e8797ce54 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties @@ -0,0 +1,11 @@ +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 + +spring.security.oauth2.client.provider.uaa.issuer-uri=http://localhost:8080/uaa/oauth/token + 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..56fb23e9d8 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + com.baeldung.cfuaa + cf-uaa-oauth2-resource-server + 0.0.1-SNAPSHOT + cf-uaa-oauth2-resource-server + Demo project for Spring Boot + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + 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..a6e846a00f --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8082 + +spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/uaa/oauth/token diff --git a/core-groovy-2/README.md b/core-groovy-2/README.md new file mode 100644 index 0000000000..33df8b107b --- /dev/null +++ b/core-groovy-2/README.md @@ -0,0 +1,10 @@ +# Groovy + +## Relevant articles: + +- [String Matching in Groovy](http://www.baeldung.com/) +- [Template Engines in Groovy](https://www.baeldung.com/groovy-template-engines) +- [Groovy def Keyword](https://www.baeldung.com/groovy-def-keyword) +- [Pattern Matching in Strings in Groovy](https://www.baeldung.com/groovy-pattern-matching) +- [Working with XML in Groovy](https://www.baeldung.com/groovy-xml) +- [Integrating Groovy into Java Applications](https://www.baeldung.com/groovy-java-applications) diff --git a/core-groovy-2/gmavenplus-pom.xml b/core-groovy-2/gmavenplus-pom.xml new file mode 100644 index 0000000000..54c89b9834 --- /dev/null +++ b/core-groovy-2/gmavenplus-pom.xml @@ -0,0 +1,178 @@ + + + 4.0.0 + core-groovy-2 + 1.0-SNAPSHOT + core-groovy-2 + jar + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + org.spockframework + spock-core + ${spock-core.version} + test + + + + + src/main/groovy + src/main/java + + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.7.0 + + + + execute + addSources + addTestSources + generateStubs + compile + generateTestStubs + compileTests + removeStubs + removeTestStubs + + + + + + org.codehaus.groovy + groovy-all + + ${groovy.version} + runtime + pom + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + + + + + junit5 + + integration-test + verify + + + + **/*Test5.java + + + + + + + maven-surefire-plugin + 2.20.1 + + false + + **/*Test.java + **/*Spec.java + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + jar-with-dependencies + + + + + com.baeldung.MyJointCompilationApp + + + + + + + make-assembly + + package + + single + + + + + + + + + + central + http://jcenter.bintray.com + + + + + UTF-8 + 1.0.0 + 2.4.0 + 1.1-groovy-2.4 + 3.9 + 1.8 + 1.2.3 + 2.5.7 + 1.6 + + + diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml new file mode 100644 index 0000000000..53b3e6a7ec --- /dev/null +++ b/core-groovy-2/pom.xml @@ -0,0 +1,186 @@ + + + 4.0.0 + core-groovy-2 + 1.0-SNAPSHOT + core-groovy-2 + jar + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + org.spockframework + spock-core + ${spock-core.version} + test + + + + + src/main/groovy + src/main/java + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + true + + + maven-compiler-plugin + 3.8.0 + + groovy-eclipse-compiler + ${java.version} + ${java.version} + + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy.version}-01 + + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + + + + + junit5 + + integration-test + verify + + + + **/*Test5.java + + + + + + + maven-surefire-plugin + 2.20.1 + + false + + **/*Test.java + **/*Spec.java + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + jar-with-dependencies + + + + + com.baeldung.MyJointCompilationApp + + + + + + + make-assembly + + package + + single + + + + + + + + + + central + http://jcenter.bintray.com + + + + + + bintray + Groovy Bintray + https://dl.bintray.com/groovy/maven + + + never + + + false + + + + + + 1.0.0 + 2.4.0 + 1.1-groovy-2.4 + 3.9 + 1.8 + 3.8.1 + 1.2.3 + 2.5.7 + UTF-8 + + + diff --git a/core-groovy-2/src/main/groovy/com/baeldung/CalcMath.groovy b/core-groovy-2/src/main/groovy/com/baeldung/CalcMath.groovy new file mode 100644 index 0000000000..0e233793b2 --- /dev/null +++ b/core-groovy-2/src/main/groovy/com/baeldung/CalcMath.groovy @@ -0,0 +1,25 @@ +package com.baeldung + +import org.slf4j.LoggerFactory + +class CalcMath { + def log = LoggerFactory.getLogger(this.getClass()) + + def calcSum(x, y) { + log.info "Executing $x + $y" + x + y + } + + /** + * example of method that in java would throw error at compile time + * @param x + * @param y + * @return + */ + def calcSum2(x, y) { + log.info "Executing $x + $y" + // DANGER! This won't throw a compilation issue and fail only at runtime!!! + calcSum3() + log.info("Logging an undefined variable: $z") + } +} \ No newline at end of file diff --git a/core-groovy-2/src/main/groovy/com/baeldung/CalcScript.groovy b/core-groovy-2/src/main/groovy/com/baeldung/CalcScript.groovy new file mode 100644 index 0000000000..84615b2217 --- /dev/null +++ b/core-groovy-2/src/main/groovy/com/baeldung/CalcScript.groovy @@ -0,0 +1,16 @@ +package com.baeldung + +def calcSum(x, y) { + x + y +} + +def calcSum2(x, y) { + // DANGER! The variable "log" may be undefined + log.info "Executing $x + $y" + // DANGER! This method doesn't exist! + calcSum3() + // DANGER! The logged variable "z" is undefined! + log.info("Logging an undefined variable: $z") +} + +calcSum(1,5) diff --git a/core-groovy-2/src/main/java/com/baeldung/MyJointCompilationApp.java b/core-groovy-2/src/main/java/com/baeldung/MyJointCompilationApp.java new file mode 100644 index 0000000000..c49f6edc30 --- /dev/null +++ b/core-groovy-2/src/main/java/com/baeldung/MyJointCompilationApp.java @@ -0,0 +1,120 @@ +package com.baeldung; + +import groovy.lang.*; +import groovy.util.GroovyScriptEngine; +import groovy.util.ResourceException; +import groovy.util.ScriptException; +import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.script.ScriptEngine; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Hello world! + * + */ +public class MyJointCompilationApp { + private final static Logger LOG = LoggerFactory.getLogger(MyJointCompilationApp.class); + private final GroovyClassLoader loader; + private final GroovyShell shell; + private final GroovyScriptEngine engine; + private final ScriptEngine engineFromFactory; + + public MyJointCompilationApp() { + loader = new GroovyClassLoader(this.getClass().getClassLoader()); + shell = new GroovyShell(loader, new Binding()); + + URL url = null; + try { + url = new File("src/main/groovy/com/baeldung/").toURI().toURL(); + } catch (MalformedURLException e) { + LOG.error("Exception while creating url", e); + } + engine = new GroovyScriptEngine(new URL[] {url}, this.getClass().getClassLoader()); + engineFromFactory = new GroovyScriptEngineFactory().getScriptEngine(); + } + + private void addWithCompiledClasses(int x, int y) { + LOG.info("Executing {} + {}", x, y); + Object result1 = new CalcScript().calcSum(x, y); + LOG.info("Result of CalcScript.calcSum() method is {}", result1); + + Object result2 = new CalcMath().calcSum(x, y); + LOG.info("Result of CalcMath.calcSum() method is {}", result2); + } + + private void addWithGroovyShell(int x, int y) throws IOException { + Script script = shell.parse(new File("src/main/groovy/com/baeldung/", "CalcScript.groovy")); + LOG.info("Executing {} + {}", x, y); + Object result = script.invokeMethod("calcSum", new Object[] { x, y }); + LOG.info("Result of CalcScript.calcSum() method is {}", result); + } + + private void addWithGroovyShellRun() throws IOException { + Script script = shell.parse(new File("src/main/groovy/com/baeldung/", "CalcScript.groovy")); + LOG.info("Executing script run method"); + Object result = script.run(); + LOG.info("Result of CalcScript.run() method is {}", result); + } + + private void addWithGroovyClassLoader(int x, int y) throws IllegalAccessException, InstantiationException, IOException { + Class calcClass = loader.parseClass( + new File("src/main/groovy/com/baeldung/", "CalcMath.groovy")); + GroovyObject calc = (GroovyObject) calcClass.newInstance(); + Object result = calc.invokeMethod("calcSum", new Object[] { x + 14, y + 14 }); + LOG.info("Result of CalcMath.calcSum() method is {}", result); + } + + private void addWithGroovyScriptEngine(int x, int y) throws IllegalAccessException, + InstantiationException, ResourceException, ScriptException { + Class calcClass = engine.loadScriptByName("CalcMath.groovy"); + GroovyObject calc = calcClass.newInstance(); + //WARNING the following will throw a ClassCastException + //((CalcMath)calc).calcSum(1,2); + Object result = calc.invokeMethod("calcSum", new Object[] { x, y }); + LOG.info("Result of CalcMath.calcSum() method is {}", result); + } + + private void addWithEngineFactory(int x, int y) throws IllegalAccessException, + InstantiationException, javax.script.ScriptException, FileNotFoundException { + Class calcClass = (Class) engineFromFactory.eval( + new FileReader(new File("src/main/groovy/com/baeldung/", "CalcMath.groovy"))); + GroovyObject calc = (GroovyObject) calcClass.newInstance(); + Object result = calc.invokeMethod("calcSum", new Object[] { x, y }); + LOG.info("Result of CalcMath.calcSum() method is {}", result); + } + + private void addWithStaticCompiledClasses() { + LOG.info("Running the Groovy classes compiled statically..."); + addWithCompiledClasses(5, 10); + + } + + private void addWithDynamicCompiledClasses() throws IOException, IllegalAccessException, InstantiationException, + ResourceException, ScriptException, javax.script.ScriptException { + LOG.info("Invocation of a dynamic groovy script..."); + addWithGroovyShell(5, 10); + LOG.info("Invocation of the run method of a dynamic groovy script..."); + addWithGroovyShellRun(); + LOG.info("Invocation of a dynamic groovy class loaded with GroovyClassLoader..."); + addWithGroovyClassLoader(10, 30); + LOG.info("Invocation of a dynamic groovy class loaded with GroovyScriptEngine..."); + addWithGroovyScriptEngine(15, 0); + LOG.info("Invocation of a dynamic groovy class loaded with GroovyScriptEngine JSR223..."); + addWithEngineFactory(5, 6); + } + + public static void main(String[] args) throws InstantiationException, IllegalAccessException, + ResourceException, ScriptException, IOException, javax.script.ScriptException { + MyJointCompilationApp myJointCompilationApp = new MyJointCompilationApp(); + LOG.info("Example of addition operation via Groovy scripts integration with Java."); + myJointCompilationApp.addWithStaticCompiledClasses(); + myJointCompilationApp.addWithDynamicCompiledClasses(); + } +} diff --git a/core-groovy-2/src/main/resources/articleEmail.template b/core-groovy-2/src/main/resources/articleEmail.template new file mode 100644 index 0000000000..26488f6288 --- /dev/null +++ b/core-groovy-2/src/main/resources/articleEmail.template @@ -0,0 +1,5 @@ +Dear <% out << (user) %>, +Please read the requested article below. +<% out << (articleText) %> +From, +<% out << (signature) %> \ No newline at end of file diff --git a/core-groovy-2/src/main/resources/email.template b/core-groovy-2/src/main/resources/email.template new file mode 100644 index 0000000000..fe4eaff851 --- /dev/null +++ b/core-groovy-2/src/main/resources/email.template @@ -0,0 +1,3 @@ +Dear $user, +Thanks for subscribing our services. +${signature} \ No newline at end of file diff --git a/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy new file mode 100644 index 0000000000..310d97d3fd --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy @@ -0,0 +1,79 @@ +package com.baeldung.defkeyword + +import org.codehaus.groovy.runtime.NullObject +import org.codehaus.groovy.runtime.typehandling.GroovyCastException + +import groovy.transform.TypeChecked +import groovy.transform.TypeCheckingMode + +@TypeChecked +class DefUnitTest extends GroovyTestCase { + + def id + def firstName = "Samwell" + def listOfCountries = ['USA', 'UK', 'FRANCE', 'INDIA'] + + @TypeChecked(TypeCheckingMode.SKIP) + def multiply(x, y) { + return x*y + } + + @TypeChecked(TypeCheckingMode.SKIP) + void testDefVariableDeclaration() { + + def list + assert list.getClass() == org.codehaus.groovy.runtime.NullObject + assert list.is(null) + + list = [1,2,4] + assert list instanceof ArrayList + } + + @TypeChecked(TypeCheckingMode.SKIP) + void testTypeVariables() { + int rate = 200 + try { + rate = [12] //GroovyCastException + rate = "nill" //GroovyCastException + } catch(GroovyCastException) { + println "Cannot assign anything other than integer" + } + } + + @TypeChecked(TypeCheckingMode.SKIP) + void testDefVariableMultipleAssignment() { + def rate + assert rate == null + assert rate.getClass() == org.codehaus.groovy.runtime.NullObject + + rate = 12 + assert rate instanceof Integer + + rate = "Not Available" + assert rate instanceof String + + rate = [1, 4] + assert rate instanceof List + + assert divide(12, 3) instanceof BigDecimal + assert divide(1, 0) instanceof String + + } + + def divide(int x, int y) { + if(y==0) { + return "Should not divide by 0" + } else { + return x/y + } + } + + def greetMsg() { + println "Hello! I am Groovy" + } + + void testDefVsType() { + def int count + assert count instanceof Integer + } +} \ No newline at end of file diff --git a/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy b/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy new file mode 100644 index 0000000000..3865bc73fa --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy @@ -0,0 +1,44 @@ +package com.baeldung.strings + +import spock.lang.Specification + +import java.util.regex.Pattern + +class StringMatchingSpec extends Specification { + + def "pattern operator example"() { + given: "a pattern" + def p = ~'foo' + + expect: + p instanceof Pattern + + and: "you can use slash strings to avoid escaping of blackslash" + def digitPattern = ~/\d*/ + digitPattern.matcher('4711').matches() + } + + def "match operator example"() { + expect: + 'foobar' ==~ /.*oba.*/ + + and: "matching is strict" + !('foobar' ==~ /foo/) + } + + def "find operator example"() { + when: "using the find operator" + def matcher = 'foo and bar, baz and buz' =~ /(\w+) and (\w+)/ + + then: "will find groups" + matcher.size() == 2 + + and: "can access groups using array" + matcher[0][0] == 'foo and bar' + matcher[1][2] == 'buz' + + and: "you can use it as a predicate" + 'foobarbaz' =~ /bar/ + } + +} diff --git a/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy new file mode 100644 index 0000000000..1846ae664c --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy @@ -0,0 +1,96 @@ +package com.baeldung.templateengine + +import groovy.text.SimpleTemplateEngine +import groovy.text.StreamingTemplateEngine +import groovy.text.GStringTemplateEngine +import groovy.text.XmlTemplateEngine +import groovy.text.XmlTemplateEngine +import groovy.text.markup.MarkupTemplateEngine +import groovy.text.markup.TemplateConfiguration + +class TemplateEnginesUnitTest extends GroovyTestCase { + + def bindMap = [user: "Norman", signature: "Baeldung"] + + void testSimpleTemplateEngine() { + def smsTemplate = 'Dear <% print user %>, Thanks for reading our Article. ${signature}' + def smsText = new SimpleTemplateEngine().createTemplate(smsTemplate).make(bindMap) + + assert smsText.toString() == "Dear Norman, Thanks for reading our Article. Baeldung" + } + + void testStreamingTemplateEngine() { + def articleEmailTemplate = new File('src/main/resources/articleEmail.template') + bindMap.articleText = """1. Overview +This is a tutorial article on Template Engines""" //can be a string larger than 64k + + def articleEmailText = new StreamingTemplateEngine().createTemplate(articleEmailTemplate).make(bindMap) + + assert articleEmailText.toString() == """Dear Norman, +Please read the requested article below. +1. Overview +This is a tutorial article on Template Engines +From, +Baeldung""" + + } + + void testGStringTemplateEngine() { + def emailTemplate = new File('src/main/resources/email.template') + def emailText = new GStringTemplateEngine().createTemplate(emailTemplate).make(bindMap) + + assert emailText.toString() == "Dear Norman,\nThanks for subscribing our services.\nBaeldung" + } + + void testXmlTemplateEngine() { + def emailXmlTemplate = ''' + def emailContent = "Thanks for subscribing our services." + + Dear ${user} + emailContent + ${signature} + + ''' + def emailXml = new XmlTemplateEngine().createTemplate(emailXmlTemplate).make(bindMap) + println emailXml.toString() + } + + void testMarkupTemplateEngineHtml() { + def emailHtmlTemplate = """html { + head { + title('Service Subscription Email') + } + body { + p('Dear Norman') + p('Thanks for subscribing our services.') + p('Baeldung') + } + }""" + + + def emailHtml = new MarkupTemplateEngine().createTemplate(emailHtmlTemplate).make() + println emailHtml.toString() + + } + + void testMarkupTemplateEngineXml() { + def emailXmlTemplate = """xmlDeclaration() + xs{ + email { + greet('Dear Norman') + content('Thanks for subscribing our services.') + signature('Baeldung') + } + } + """ + TemplateConfiguration config = new TemplateConfiguration() + config.autoIndent = true + config.autoEscape = true + config.autoNewLine = true + + def emailXml = new MarkupTemplateEngine(config).createTemplate(emailXmlTemplate).make() + + println emailXml.toString() + } + +} \ No newline at end of file diff --git a/core-groovy-2/src/test/groovy/com/baeldung/xml/MarkupBuilderUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/xml/MarkupBuilderUnitTest.groovy new file mode 100644 index 0000000000..c0c8c98392 --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/xml/MarkupBuilderUnitTest.groovy @@ -0,0 +1,40 @@ +package com.baeldung.xml + +import groovy.xml.MarkupBuilder +import groovy.xml.XmlUtil +import spock.lang.Specification + +class MarkupBuilderUnitTest extends Specification { + + def xmlFile = getClass().getResource("articles_short_formatted.xml") + +def "Should create XML properly"() { + given: "Node structures" + + when: "Using MarkupBuilderUnitTest to create com.baeldung.xml structure" + def writer = new StringWriter() + new MarkupBuilder(writer).articles { + article { + title('First steps in Java') + author(id: '1') { + firstname('Siena') + lastname('Kerr') + } + 'release-date'('2018-12-01') + } + article { + title('Dockerize your SpringBoot application') + author(id: '2') { + firstname('Jonas') + lastname('Lugo') + } + 'release-date'('2018-12-01') + } + } + + then: "Xml is created properly" + XmlUtil.serialize(writer.toString()) == XmlUtil.serialize(xmlFile.text) +} + + +} diff --git a/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlParserUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlParserUnitTest.groovy new file mode 100644 index 0000000000..ada47406a1 --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlParserUnitTest.groovy @@ -0,0 +1,94 @@ +package com.baeldung.xml + + +import spock.lang.Shared +import spock.lang.Specification + +class XmlParserUnitTest extends Specification { + + def xmlFile = getClass().getResourceAsStream("articles.xml") + + @Shared + def parser = new XmlParser() + + def "Should read XML file properly"() { + given: "XML file" + + when: "Using XmlParser to read file" + def articles = parser.parse(xmlFile) + + then: "Xml is loaded properly" + articles.'*'.size() == 4 + articles.article[0].author.firstname.text() == "Siena" + articles.article[2].'release-date'.text() == "2018-06-12" + articles.article[3].title.text() == "Java 12 insights" + articles.article.find { it.author.'@id'.text() == "3" }.author.firstname.text() == "Daniele" + } + + + def "Should add node to existing com.baeldung.xml using NodeBuilder"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Adding node to com.baeldung.xml" + def articleNode = new NodeBuilder().article(id: '5') { + title('Traversing XML in the nutshell') + author { + firstname('Martin') + lastname('Schmidt') + } + 'release-date'('2019-05-18') + } + articles.append(articleNode) + + then: "Node is added to com.baeldung.xml properly" + articles.'*'.size() == 5 + articles.article[4].title.text() == "Traversing XML in the nutshell" + } + + def "Should replace node"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Adding node to com.baeldung.xml" + def articleNode = new NodeBuilder().article(id: '5') { + title('Traversing XML in the nutshell') + author { + firstname('Martin') + lastname('Schmidt') + } + 'release-date'('2019-05-18') + } + articles.article[0].replaceNode(articleNode) + + then: "Node is added to com.baeldung.xml properly" + articles.'*'.size() == 4 + articles.article[0].title.text() == "Traversing XML in the nutshell" + } + + def "Should modify node"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Changing value of one of the nodes" + articles.article.each { it.'release-date'[0].value = "2019-05-18" } + + then: "XML is updated" + articles.article.findAll { it.'release-date'.text() != "2019-05-18" }.isEmpty() + } + + def "Should remove article from com.baeldung.xml"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Removing all articles but with id==3" + articles.article + .findAll { it.author.'@id'.text() != "3" } + .each { articles.remove(it) } + + then: "There is only one article left" + articles.children().size() == 1 + articles.article[0].author.'@id'.text() == "3" + } + +} diff --git a/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlSlurperUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlSlurperUnitTest.groovy new file mode 100644 index 0000000000..ffeaa46fce --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/xml/XmlSlurperUnitTest.groovy @@ -0,0 +1,102 @@ +package com.baeldung.xml + + +import groovy.xml.XmlUtil +import spock.lang.Shared +import spock.lang.Specification + +class XmlSlurperUnitTest extends Specification { + + def xmlFile = getClass().getResourceAsStream("articles.xml") + + @Shared + def parser = new XmlSlurper() + + def "Should read XML file properly"() { + given: "XML file" + + when: "Using XmlSlurper to read file" + def articles = parser.parse(xmlFile) + + then: "Xml is loaded properly" + articles.'*'.size() == 4 + articles.article[0].author.firstname == "Siena" + articles.article[2].'release-date' == "2018-06-12" + articles.article[3].title == "Java 12 insights" + articles.article.find { it.author.'@id' == "3" }.author.firstname == "Daniele" + } + + def "Should add node to existing com.baeldung.xml"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Adding node to com.baeldung.xml" + articles.appendNode { + article(id: '5') { + title('Traversing XML in the nutshell') + author { + firstname('Martin') + lastname('Schmidt') + } + 'release-date'('2019-05-18') + } + } + + articles = parser.parseText(XmlUtil.serialize(articles)) + + then: "Node is added to com.baeldung.xml properly" + articles.'*'.size() == 5 + articles.article[4].title == "Traversing XML in the nutshell" + } + + def "Should modify node"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Changing value of one of the nodes" + articles.article.each { it.'release-date' = "2019-05-18" } + + then: "XML is updated" + articles.article.findAll { it.'release-date' != "2019-05-18" }.isEmpty() + } + + def "Should replace node"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Replacing node" + articles.article[0].replaceNode { + article(id: '5') { + title('Traversing XML in the nutshell') + author { + firstname('Martin') + lastname('Schmidt') + } + 'release-date'('2019-05-18') + } + } + + articles = parser.parseText(XmlUtil.serialize(articles)) + + then: "Node is replaced properly" + articles.'*'.size() == 4 + articles.article[0].title == "Traversing XML in the nutshell" + } + + def "Should remove article from com.baeldung.xml"() { + given: "XML object" + def articles = parser.parse(xmlFile) + + when: "Removing all articles but with id==3" + articles.article + .findAll { it.author.'@id' != "3" } + .replaceNode {} + + articles = parser.parseText(XmlUtil.serialize(articles)) + + then: "There is only one article left" + articles.children().size() == 1 + articles.article[0].author.'@id' == "3" + } + +} diff --git a/core-groovy-2/src/test/resources/com/baeldung/xml/articles.xml b/core-groovy-2/src/test/resources/com/baeldung/xml/articles.xml new file mode 100644 index 0000000000..ef057405f5 --- /dev/null +++ b/core-groovy-2/src/test/resources/com/baeldung/xml/articles.xml @@ -0,0 +1,34 @@ + +
+ First steps in Java + + Siena + Kerr + + 2018-12-01 +
+
+ Dockerize your SpringBoot application + + Jonas + Lugo + + 2018-12-01 +
+
+ SpringBoot tutorial + + Daniele + Ferguson + + 2018-06-12 +
+
+ Java 12 insights + + Siena + Kerr + + 2018-07-22 +
+
diff --git a/core-groovy-2/src/test/resources/com/baeldung/xml/articles_short_formatted.xml b/core-groovy-2/src/test/resources/com/baeldung/xml/articles_short_formatted.xml new file mode 100644 index 0000000000..6492020e03 --- /dev/null +++ b/core-groovy-2/src/test/resources/com/baeldung/xml/articles_short_formatted.xml @@ -0,0 +1,18 @@ + +
+ First steps in Java + + Siena + Kerr + + 2018-12-01 +
+
+ Dockerize your SpringBoot application + + Jonas + Lugo + + 2018-12-01 +
+
diff --git a/core-groovy-collections/README.md b/core-groovy-collections/README.md new file mode 100644 index 0000000000..aeba8933be --- /dev/null +++ b/core-groovy-collections/README.md @@ -0,0 +1,6 @@ +# Groovy + +## Relevant articles: + +- [Maps in Groovy](https://www.baeldung.com/groovy-maps) + diff --git a/core-groovy-collections/pom.xml b/core-groovy-collections/pom.xml new file mode 100644 index 0000000000..bf3ae26592 --- /dev/null +++ b/core-groovy-collections/pom.xml @@ -0,0 +1,131 @@ + + + 4.0.0 + core-groovy-collections + 1.0-SNAPSHOT + core-groovy-collections + jar + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.codehaus.groovy + groovy + ${groovy.version} + + + org.codehaus.groovy + groovy-all + ${groovy-all.version} + pom + + + org.codehaus.groovy + groovy-dateutil + ${groovy.version} + + + org.codehaus.groovy + groovy-sql + ${groovy-sql.version} + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + org.spockframework + spock-core + ${spock-core.version} + test + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + ${gmavenplus-plugin.version} + + + + addSources + addTestSources + compile + compileTests + + + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + + + + + junit5 + + integration-test + verify + + + + **/*Test5.java + + + + + + + maven-surefire-plugin + 2.20.1 + + false + + **/*Test.java + **/*Spec.java + + + + + + + + + central + http://jcenter.bintray.com + + + + + 1.0.0 + 2.5.6 + 2.5.6 + 2.5.6 + 2.4.0 + 1.1-groovy-2.4 + 1.6 + + + diff --git a/core-groovy-collections/src/test/groovy/com/baeldung/map/MapTest.groovy b/core-groovy-collections/src/test/groovy/com/baeldung/map/MapTest.groovy new file mode 100644 index 0000000000..c6105eb1c4 --- /dev/null +++ b/core-groovy-collections/src/test/groovy/com/baeldung/map/MapTest.groovy @@ -0,0 +1,148 @@ +package com.baeldung.map; + +import static groovy.test.GroovyAssert.* +import org.junit.Test + +class MapTest{ + + @Test + void createMap() { + + def emptyMap = [:] + assertNotNull(emptyMap) + + assertTrue(emptyMap instanceof java.util.LinkedHashMap) + + def map = [name:"Jerry", age: 42, city: "New York"] + assertTrue(map.size() == 3) + } + + @Test + void addItemsToMap() { + + def map = [name:"Jerry"] + + map["age"] = 42 + + map.city = "New York" + + def hobbyLiteral = "hobby" + def hobbyMap = [(hobbyLiteral): "Singing"] + map.putAll(hobbyMap) + + assertTrue(map == [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]) + assertTrue(hobbyMap.hobby == "Singing") + assertTrue(hobbyMap[hobbyLiteral] == "Singing") + + map.plus([1:20]) // returns new map + + map << [2:30] + + } + + @Test + void getItemsFromMap() { + + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + assertTrue(map["name"] == "Jerry") + + assertTrue(map.name == "Jerry") + + def propertyAge = "age" + assertTrue(map[propertyAge] == 42) + } + + @Test + void removeItemsFromMap() { + + def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49] + + def minusMap = map.minus([2:42, 4:34]); + assertTrue(minusMap == [1:20, a:30, ba:67, 6:39, 7:49]) + + minusMap.removeAll{it -> it.key instanceof String} + assertTrue( minusMap == [ 1:20, 6:39, 7:49]) + + minusMap.retainAll{it -> it.value %2 == 0} + assertTrue( minusMap == [1:20]) + } + + @Test + void iteratingOnMaps(){ + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + map.each{ entry -> println "$entry.key: $entry.value" } + + map.eachWithIndex{ entry, i -> println "$i $entry.key: $entry.value" } + + map.eachWithIndex{ key, value, i -> println "$i $key: $value" } + } + + @Test + void filteringAndSearchingMaps(){ + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + assertTrue(map.find{ it.value == "New York"}.key == "city") + + assertTrue(map.findAll{ it.value == "New York"} == [city : "New York"]) + + map.grep{it.value == "New York"}.each{ it -> assertTrue(it.key == "city" && it.value == "New York")} + + assertTrue(map.every{it -> it.value instanceof String} == false) + + assertTrue(map.any{it -> it.value instanceof String} == true) + } + + @Test + void collect(){ + + def map = [1: [name:"Jerry", age: 42, city: "New York"], + 2: [name:"Long", age: 25, city: "New York"], + 3: [name:"Dustin", age: 29, city: "New York"], + 4: [name:"Dustin", age: 34, city: "New York"]] + + def names = map.collect{entry -> entry.value.name} // returns only list + assertTrue(names == ["Jerry", "Long", "Dustin", "Dustin"]) + + def uniqueNames = map.collect([] as HashSet){entry -> entry.value.name} + assertTrue(uniqueNames == ["Jerry", "Long", "Dustin"] as Set) + + def idNames = map.collectEntries{key, value -> [key, value.name]} + assertTrue(idNames == [1:"Jerry", 2: "Long", 3:"Dustin", 4: "Dustin"]) + + def below30Names = map.findAll{it.value.age < 30}.collect{key, value -> value.name} + assertTrue(below30Names == ["Long", "Dustin"]) + + + } + + @Test + void group(){ + def map = [1:20, 2: 40, 3: 11, 4: 93] + + def subMap = map.groupBy{it.value % 2} + println subMap + assertTrue(subMap == [0:[1:20, 2:40 ], 1:[3:11, 4:93]]) + + def keySubMap = map.subMap([1, 2]) + assertTrue(keySubMap == [1:20, 2:40]) + + } + + @Test + void sorting(){ + def map = [ab:20, a: 40, cb: 11, ba: 93] + + def naturallyOrderedMap = map.sort() + assertTrue([a:40, ab:20, ba:93, cb:11] == naturallyOrderedMap) + + def compSortedMap = map.sort({ k1, k2 -> k1 <=> k2 } as Comparator) + assertTrue([a:40, ab:20, ba:93, cb:11] == compSortedMap) + + def cloSortedMap = map.sort({ it1, it2 -> it1.value <=> it1.value }) + assertTrue([cb:11, ab:20, a:40, ba:93] == cloSortedMap) + + } + +} diff --git a/core-groovy/.gitignore b/core-groovy/.gitignore new file mode 100644 index 0000000000..09220fdf52 --- /dev/null +++ b/core-groovy/.gitignore @@ -0,0 +1 @@ +/src/main/resources/ioSerializedObject.txt \ No newline at end of file diff --git a/core-groovy/README.md b/core-groovy/README.md index 71788acdb7..321c37be8d 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -4,3 +4,12 @@ - [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) +- [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) +- [Closures in Groovy](https://www.baeldung.com/groovy-closures) +- [Finding Elements in Collections in Groovy](https://www.baeldung.com/groovy-collections-find-elements) +- [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) \ No newline at end of file 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/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/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/main/groovy/com/baeldung/file/ReadFile.groovy b/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy new file mode 100644 index 0000000000..4239fa534c --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/file/ReadFile.groovy @@ -0,0 +1,107 @@ +package com.baeldung.file + +class ReadFile { + + /** + * reads file content line by line using withReader and reader.readLine + * @param filePath + * @return + */ + int readFileLineByLine(String filePath) { + File file = new File(filePath) + def line, noOfLines = 0; + file.withReader { reader -> + while ((line = reader.readLine())!=null) + { + println "${line}" + noOfLines++ + } + } + return noOfLines + } + + /** + * reads file content in list of lines + * @param filePath + * @return + */ + List readFileInList(String filePath) { + File file = new File(filePath) + def lines = file.readLines() + return lines + } + + /** + * reads file content in string using File.text + * @param filePath + * @return + */ + String readFileString(String filePath) { + File file = new File(filePath) + String fileContent = file.text + return fileContent + } + + /** + * reads file content in string with encoding using File.getText + * @param filePath + * @return + */ + String readFileStringWithCharset(String filePath) { + File file = new File(filePath) + String utf8Content = file.getText("UTF-8") + return utf8Content + } + + /** + * reads content of binary file and returns byte array + * @param filePath + * @return + */ + byte[] readBinaryFile(String filePath) { + File file = new File(filePath) + byte[] binaryContent = file.bytes + return binaryContent + } + + /** + * More Examples of reading a file + * @return + */ + def moreExamples() { + + //with reader with utf-8 + new File("src/main/resources/utf8Content.html").withReader('UTF-8') { reader -> + def line + while ((line = reader.readLine())!=null) { + println "${line}" + } + } + + //collect api + def list = new File("src/main/resources/fileContent.txt").collect {it} + + //as operator + def array = new File("src/main/resources/fileContent.txt") as String[] + + //eachline + new File("src/main/resources/fileContent.txt").eachLine { line -> + println line + } + + //newInputStream with eachLine + def is = new File("src/main/resources/fileContent.txt").newInputStream() + is.eachLine { + println it + } + is.close() + + //withInputStream + new File("src/main/resources/fileContent.txt").withInputStream { stream -> + stream.eachLine { line -> + println line + } + } + } + +} \ No newline at end of file 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/groovy/com/baeldung/strings/Concatenate.groovy b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy new file mode 100644 index 0000000000..b3a0852a0b --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy @@ -0,0 +1,43 @@ +package com.baeldung.strings; + +class Concatenate { + String first = 'Hello' + String last = 'Groovy' + + String doSimpleConcat() { + return 'My name is ' + first + ' ' + last + } + + String doConcatUsingGString() { + return "My name is $first $last" + } + + String doConcatUsingGStringClosures() { + return "My name is ${-> first} ${-> last}" + } + + String doConcatUsingStringConcatMethod() { + return 'My name is '.concat(first).concat(' ').concat(last) + } + + String doConcatUsingLeftShiftOperator() { + return 'My name is ' << first << ' ' << last + } + + String doConcatUsingArrayJoinMethod() { + return ['My name is', first, last].join(' ') + } + + String doConcatUsingArrayInjectMethod() { + return [first,' ', last] + .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString() + } + + String doConcatUsingStringBuilder() { + return new StringBuilder().append('My name is ').append(first).append(' ').append(last) + } + + String doConcatUsingStringBuffer() { + return new StringBuffer().append('My name is ').append(first).append(' ').append(last) + } +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy new file mode 100644 index 0000000000..6ec5cda571 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy @@ -0,0 +1,8 @@ +package com.baeldung.traits + +trait AnimalTrait { + + String basicBehavior() { + return "Animalistic!!" + } +} \ No newline at end of file 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/Dog.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy new file mode 100644 index 0000000000..3e0677ba18 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy @@ -0,0 +1,9 @@ +package com.baeldung.traits + +class Dog implements WalkingTrait, SpeakingTrait { + + String speakAndWalk() { + WalkingTrait.super.speakAndWalk() + } + +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy new file mode 100644 index 0000000000..b3e4285476 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy @@ -0,0 +1,12 @@ +package com.baeldung.traits + +class Employee implements UserTrait { + + String name() { + return 'Bob' + } + + String lastName() { + return "Marley" + } +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy new file mode 100644 index 0000000000..e78d59bbfd --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy @@ -0,0 +1,6 @@ +package com.baeldung.traits + +interface Human { + + String lastName() +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy new file mode 100644 index 0000000000..f437a94bd9 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy @@ -0,0 +1,13 @@ +package com.baeldung.traits + +trait SpeakingTrait { + + String basicAbility() { + return "Speaking!!" + } + + String speakAndWalk() { + return "Speak and walk!!" + } + +} \ 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 new file mode 100644 index 0000000000..0d395bffcd --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy @@ -0,0 +1,36 @@ +package com.baeldung.traits + +trait UserTrait implements Human { + + String sayHello() { + return "Hello!" + } + + abstract String name() + + String showName() { + return "Hello, ${name()}!" + } + + private String greetingMessage() { + return 'Hello, from a private method!' + } + + String greet() { + def msg = greetingMessage() + println msg + msg + } + + def self() { + return this + } + + String showLastName() { + return "Hello, ${lastName()}!" + } + + String email + String address +} + \ No newline at end of file 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/WalkingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy new file mode 100644 index 0000000000..66cff8809f --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy @@ -0,0 +1,13 @@ +package com.baeldung.traits + +trait WalkingTrait { + + String basicAbility() { + return "Walking!!" + } + + String speakAndWalk() { + return "Walk and speak!!" + } + +} \ 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/main/resources/binaryExample.jpg b/core-groovy/src/main/resources/binaryExample.jpg new file mode 100644 index 0000000000..4b32645ac9 Binary files /dev/null and b/core-groovy/src/main/resources/binaryExample.jpg differ diff --git a/core-groovy/src/main/resources/fileContent.txt b/core-groovy/src/main/resources/fileContent.txt new file mode 100644 index 0000000000..643e4af3de --- /dev/null +++ b/core-groovy/src/main/resources/fileContent.txt @@ -0,0 +1,3 @@ +Line 1 : Hello World!!! +Line 2 : This is a file content. +Line 3 : String content diff --git a/core-groovy/src/main/resources/ioData.txt b/core-groovy/src/main/resources/ioData.txt new file mode 100644 index 0000000000..d2741339d1 Binary files /dev/null and b/core-groovy/src/main/resources/ioData.txt differ diff --git a/core-groovy/src/main/resources/ioInput.txt b/core-groovy/src/main/resources/ioInput.txt new file mode 100644 index 0000000000..b180256dd5 --- /dev/null +++ b/core-groovy/src/main/resources/ioInput.txt @@ -0,0 +1,4 @@ +First line of text +Second line of text +Third line of text +Fourth line of text \ No newline at end of file diff --git a/core-groovy/src/main/resources/ioOutput.txt b/core-groovy/src/main/resources/ioOutput.txt new file mode 100644 index 0000000000..bcf76c43d8 --- /dev/null +++ b/core-groovy/src/main/resources/ioOutput.txt @@ -0,0 +1,3 @@ +Line one of output example +Line two of output example +Line three of output example \ No newline at end of file diff --git a/core-groovy/src/main/resources/sample.png b/core-groovy/src/main/resources/sample.png new file mode 100644 index 0000000000..7d473430b7 Binary files /dev/null and b/core-groovy/src/main/resources/sample.png differ diff --git a/core-groovy/src/main/resources/utf8Content.html b/core-groovy/src/main/resources/utf8Content.html new file mode 100644 index 0000000000..61ff338f6c --- /dev/null +++ b/core-groovy/src/main/resources/utf8Content.html @@ -0,0 +1,12 @@ + + + + +
+ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ
+ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ
+ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ
+
+ + \ 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 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) + } + + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy new file mode 100644 index 0000000000..a479c265c4 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy @@ -0,0 +1,70 @@ +package com.baeldung.file + +import spock.lang.Specification + +class ReadFileUnitTest extends Specification { + + ReadFile readFile + + void setup () { + readFile = new ReadFile() + } + + def 'Should return number of lines in File using ReadFile.readFileLineByLine given filePath' () { + given: + def filePath = "src/main/resources/fileContent.txt" + when: + def noOfLines = readFile.readFileLineByLine(filePath) + then: + noOfLines + noOfLines instanceof Integer + assert noOfLines, 3 + } + + def 'Should return File Content in list of lines using ReadFile.readFileInList given filePath' () { + given: + def filePath = "src/main/resources/fileContent.txt" + when: + def lines = readFile.readFileInList(filePath) + then: + lines + lines instanceof List + assert lines.size(), 3 + } + + def 'Should return file content in string using ReadFile.readFileString given filePath' () { + given: + def filePath = "src/main/resources/fileContent.txt" + when: + def fileContent = readFile.readFileString(filePath) + then: + fileContent + fileContent instanceof String + fileContent.contains("""Line 1 : Hello World!!! +Line 2 : This is a file content. +Line 3 : String content""") + + } + + def 'Should return UTF-8 encoded file content in string using ReadFile.readFileStringWithCharset given filePath' () { + given: + def filePath = "src/main/resources/utf8Content.html" + when: + def encodedContent = readFile.readFileStringWithCharset(filePath) + then: + encodedContent + encodedContent instanceof String + } + + def 'Should return binary file content in byte array using ReadFile.readBinaryFile given filePath' () { + given: + def filePath = "src/main/resources/sample.png" + when: + def binaryContent = readFile.readBinaryFile(filePath) + then: + binaryContent + binaryContent instanceof byte[] + binaryContent.length == 329 + } + +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy new file mode 100644 index 0000000000..32a21f6b38 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy @@ -0,0 +1,53 @@ +package com.baeldung.io + +import static org.junit.Assert.* + +import org.junit.Test + +class DataAndObjectsUnitTest { + @Test + void whenUsingWithDataOutputStream_thenDataIsSerializedToAFile() { + String message = 'This is a serialized string' + int length = message.length() + boolean valid = true + new File('src/main/resources/ioData.txt').withDataOutputStream { out -> + 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) + def serializedDataFile = new File('src/main/resources/ioSerializedObject.txt') + serializedDataFile.createNewFile() + serializedDataFile.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()) + } +} 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..7771028132 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy @@ -0,0 +1,173 @@ +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 copyList = new ArrayList(arrList) + assertTrue(copyList == arrList) + + def cloneList = arrList.clone() + assertTrue(cloneList == 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 filterList = [2, 1, 3, 4, 5, 6, 76] + + assertTrue(filterList.find{it > 3} == 4) + + 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}) + + } + + @Test + void testGetUniqueItemsInAList(){ + assertTrue([1, 3, 3, 4].toUnique() == [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"]) + } + + @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 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) + } +} \ No newline at end of file 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/MapTest.groovy b/core-groovy/src/test/groovy/com/baeldung/map/MapTest.groovy new file mode 100644 index 0000000000..f1d528207f --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/map/MapTest.groovy @@ -0,0 +1,148 @@ +package com.baeldung.groovy.map; + +import static groovy.test.GroovyAssert.* +import org.junit.Test + +class MapTest{ + + @Test + void createMap() { + + def emptyMap = [:] + assertNotNull(emptyMap) + + assertTrue(emptyMap instanceof java.util.LinkedHashMap) + + def map = [name:"Jerry", age: 42, city: "New York"] + assertTrue(map.size() == 3) + } + + @Test + void addItemsToMap() { + + def map = [name:"Jerry"] + + map["age"] = 42 + + map.city = "New York" + + def hobbyLiteral = "hobby" + def hobbyMap = [(hobbyLiteral): "Singing"] + map.putAll(hobbyMap) + + assertTrue(map == [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]) + assertTrue(hobbyMap.hobby == "Singing") + assertTrue(hobbyMap[hobbyLiteral] == "Singing") + + map.plus([1:20]) // returns new map + + map << [2:30] + + } + + @Test + void getItemsFromMap() { + + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + assertTrue(map["name"] == "Jerry") + + assertTrue(map.name == "Jerry") + + def propertyAge = "age" + assertTrue(map[propertyAge] == 42) + } + + @Test + void removeItemsFromMap() { + + def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49] + + def minusMap = map.minus([2:42, 4:34]); + assertTrue(minusMap == [1:20, a:30, ba:67, 6:39, 7:49]) + + minusMap.removeAll{it -> it.key instanceof String} + assertTrue( minusMap == [ 1:20, 6:39, 7:49]) + + minusMap.retainAll{it -> it.value %2 == 0} + assertTrue( minusMap == [1:20]) + } + + @Test + void iteratingOnMaps(){ + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + map.each{ entry -> println "$entry.key: $entry.value" } + + map.eachWithIndex{ entry, i -> println "$i $entry.key: $entry.value" } + + map.eachWithIndex{ key, value, i -> println "$i $key: $value" } + } + + @Test + void filteringAndSearchingMaps(){ + def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"] + + assertTrue(map.find{ it.value == "New York"}.key == "city") + + assertTrue(map.findAll{ it.value == "New York"} == [city : "New York"]) + + map.grep{it.value == "New York"}.each{ it -> assertTrue(it.key == "city" && it.value == "New York")} + + assertTrue(map.every{it -> it.value instanceof String} == false) + + assertTrue(map.any{it -> it.value instanceof String} == true) + } + + @Test + void collect(){ + + def map = [1: [name:"Jerry", age: 42, city: "New York"], + 2: [name:"Long", age: 25, city: "New York"], + 3: [name:"Dustin", age: 29, city: "New York"], + 4: [name:"Dustin", age: 34, city: "New York"]] + + def names = map.collect{entry -> entry.value.name} // returns only list + assertTrue(names == ["Jerry", "Long", "Dustin", "Dustin"]) + + def uniqueNames = map.collect([] as HashSet){entry -> entry.value.name} + assertTrue(uniqueNames == ["Jerry", "Long", "Dustin"] as Set) + + def idNames = map.collectEntries{key, value -> [key, value.name]} + assertTrue(idNames == [1:"Jerry", 2: "Long", 3:"Dustin", 4: "Dustin"]) + + def below30Names = map.findAll{it.value.age < 30}.collect{key, value -> value.name} + assertTrue(below30Names == ["Long", "Dustin"]) + + + } + + @Test + void group(){ + def map = [1:20, 2: 40, 3: 11, 4: 93] + + def subMap = map.groupBy{it.value % 2} + println subMap + assertTrue(subMap == [0:[1:20, 2:40 ], 1:[3:11, 4:93]]) + + def keySubMap = map.subMap([1, 2]) + assertTrue(keySubMap == [1:20, 2:40]) + + } + + @Test + void sorting(){ + def map = [ab:20, a: 40, cb: 11, ba: 93] + + def naturallyOrderedMap = map.sort() + assertTrue([a:40, ab:20, ba:93, cb:11] == naturallyOrderedMap) + + def compSortedMap = map.sort({ k1, k2 -> k1 <=> k2 } as Comparator) + assertTrue([a:40, ab:20, ba:93, cb:11] == compSortedMap) + + def cloSortedMap = map.sort({ it1, it2 -> it1.value <=> it1.value }) + assertTrue([cb:11, ab:20, a:40, ba:93] == cloSortedMap) + + } + +} 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..0d6bbed04b --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy @@ -0,0 +1,154 @@ +package com.baeldung.map + +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 = [ + '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" + } + } + + @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 diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy new file mode 100644 index 0000000000..3ef4a5d460 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy @@ -0,0 +1,101 @@ +import com.baeldung.strings.Concatenate; + +class ConcatenateTest extends GroovyTestCase { + + void testSimpleConcat() { + def name = new Concatenate() + name.first = 'Joe'; + name.last = 'Smith'; + def expected = 'My name is Joe Smith' + assertToString(name.doSimpleConcat(), expected) + } + + void testConcatUsingGString() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingGString(), expected) + } + + void testConcatUsingGStringClosures() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingGStringClosures(), expected) + } + + void testConcatUsingStringConcatMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringConcatMethod(), expected) + } + + void testConcatUsingLeftShiftOperator() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingLeftShiftOperator(), expected) + } + + void testConcatUsingArrayJoinMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingArrayJoinMethod(), expected) + } + + void testConcatUsingArrayInjectMethod() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingArrayInjectMethod(), expected) + } + + void testConcatUsingStringBuilder() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringBuilder(), expected) + } + + void testConcatUsingStringBuffer() { + def name = new Concatenate() + name.first = "Joe"; + name.last = "Smith"; + def expected = "My name is Joe Smith" + assertToString(name.doConcatUsingStringBuffer(), expected) + } + + void testConcatMultilineUsingStringConcatMethod() { + def name = new Concatenate() + name.first = '''Joe + Smith + '''; + name.last = 'Junior'; + def expected = '''My name is Joe + Smith + Junior'''; + assertToString(name.doConcatUsingStringConcatMethod(), expected) + } + + void testGStringvsClosure(){ + def first = "Joe"; + def last = "Smith"; + def eagerGString = "My name is $first $last" + def lazyGString = "My name is ${-> first} ${-> last}" + + assert eagerGString == "My name is Joe Smith" + assert lazyGString == "My name is Joe Smith" + first = "David"; + assert eagerGString == "My name is Joe Smith" + assert lazyGString == "My name is David Smith" + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy new file mode 100644 index 0000000000..3865bc73fa --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy @@ -0,0 +1,44 @@ +package com.baeldung.strings + +import spock.lang.Specification + +import java.util.regex.Pattern + +class StringMatchingSpec extends Specification { + + def "pattern operator example"() { + given: "a pattern" + def p = ~'foo' + + expect: + p instanceof Pattern + + and: "you can use slash strings to avoid escaping of blackslash" + def digitPattern = ~/\d*/ + digitPattern.matcher('4711').matches() + } + + def "match operator example"() { + expect: + 'foobar' ==~ /.*oba.*/ + + and: "matching is strict" + !('foobar' ==~ /foo/) + } + + def "find operator example"() { + when: "using the find operator" + def matcher = 'foo and bar, baz and buz' =~ /(\w+) and (\w+)/ + + then: "will find groups" + matcher.size() == 2 + + and: "can access groups using array" + matcher[0][0] == 'foo and bar' + matcher[1][2] == 'buz' + + and: "you can use it as a predicate" + 'foobarbaz' =~ /bar/ + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy new file mode 100644 index 0000000000..c043723d95 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy @@ -0,0 +1,19 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class CharacterInGroovy { + + @Test + void 'character'() { + char a = 'A' as char + char b = 'B' as char + char c = (char) 'C' + + Assert.assertTrue(a instanceof Character) + Assert.assertTrue(b instanceof Character) + Assert.assertTrue(c instanceof Character) + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy new file mode 100644 index 0000000000..db8ba68c8f --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy @@ -0,0 +1,24 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Test + +class DollarSlashyString { + + @Test + void 'dollar slashy string'() { + def name = "John" + + def dollarSlashy = $/ + Hello $name!, + + I can show you $ sign or escaped dollar sign: $$ + Both slashes works: \ or /, but we can still escape it: $/ + + We have to escape opening and closing delimiter: + - $$$/ + - $/$$ + /$ + + print(dollarSlashy) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy new file mode 100644 index 0000000000..a730244d0a --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy @@ -0,0 +1,67 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class DoubleQuotedString { + + @Test + void 'escape double quoted string'() { + def example = "Hello \"world\"!" + + println(example) + } + + @Test + void 'String ang GString'() { + def string = "example" + def stringWithExpression = "example${2}" + + Assert.assertTrue(string instanceof String) + Assert.assertTrue(stringWithExpression instanceof GString) + Assert.assertTrue(stringWithExpression.toString() instanceof String) + } + + @Test + void 'placeholder with variable'() { + def name = "John" + def helloName = "Hello $name!".toString() + + Assert.assertEquals("Hello John!", helloName) + } + + @Test + void 'placeholder with expression'() { + def result = "result is ${2 * 2}".toString() + + Assert.assertEquals("result is 4", result) + } + + @Test + void 'placeholder with dotted access'() { + def person = [name: 'John'] + + def myNameIs = "I'm $person.name, and you?".toString() + + Assert.assertEquals("I'm John, and you?", myNameIs) + } + + @Test + void 'placeholder with method call'() { + def name = 'John' + + def result = "Uppercase name: ${name.toUpperCase()}".toString() + + Assert.assertEquals("Uppercase name: JOHN", result) + } + + + @Test + void 'GString and String hashcode'() { + def string = "2+2 is 4" + def gstring = "2+2 is ${4}" + + Assert.assertTrue(string.hashCode() != gstring.hashCode()) + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy new file mode 100644 index 0000000000..569991b788 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy @@ -0,0 +1,15 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class SingleQuotedString { + + @Test + void 'single quoted string'() { + def example = 'Hello world' + + Assert.assertEquals('Hello world!', 'Hello' + ' world!') + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy new file mode 100644 index 0000000000..09ba35e17e --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy @@ -0,0 +1,31 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class SlashyString { + + @Test + void 'slashy string'() { + def pattern = /.*foobar.*\/hello.*/ + + Assert.assertTrue("I'm matching foobar /hello regexp pattern".matches(pattern)) + } + + void 'wont compile'() { +// if ('' == //) { +// println("I can't compile") +// } + } + + @Test + void 'interpolate and multiline'() { + def name = 'John' + + def example = / + Hello $name + second line + / + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy new file mode 100644 index 0000000000..e45f352285 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy @@ -0,0 +1,26 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class Strings { + + @Test + void 'string interpolation '() { + def name = "Kacper" + + def result = "Hello ${name}!" + + Assert.assertEquals("Hello Kacper!", result.toString()) + } + + @Test + void 'string concatenation'() { + def first = "first" + def second = "second" + + def concatenation = first + second + + Assert.assertEquals("firstsecond", concatenation) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy new file mode 100644 index 0000000000..cbbb1a4665 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy @@ -0,0 +1,19 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Test + +class TripleDoubleQuotedString { + + @Test + void 'triple-quoted strings with interpolation'() { + def name = "John" + + def multiLine = """ + I'm $name. + "This is quotation" + """ + + println(multiLine) + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy new file mode 100644 index 0000000000..24d55b8a2a --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy @@ -0,0 +1,67 @@ +package groovy.com.baeldung.stringtypes + +import org.junit.Assert +import org.junit.Test + +class TripleSingleQuotedString { + + def 'formatted json'() { + def jsonContent = ''' + { + "name": "John", + "age": 20, + "birthDate": null + } + ''' + } + + def 'triple single quoted'() { + def triple = '''im triple single quoted string''' + } + + @Test + void 'triple single quoted with multiline string'() { + def triple = ''' + firstline + secondline + ''' + + Assert.assertTrue(triple.startsWith("\n")) + } + + @Test + void 'triple single quoted with multiline string with stripIndent() and removing newline characters'() { + def triple = '''\ + firstline + secondline'''.stripIndent() + + Assert.assertEquals("firstline\nsecondline", triple) + } + + @Test + void 'triple single quoted with multiline string with last line with only whitespaces'() { + def triple = '''\ + firstline + secondline\ + '''.stripIndent() + + println(triple) + } + + @Test + void 'triple single quoted with multiline string with stripMargin(Character) and removing newline characters'() { + def triple = '''\ + |firstline + |secondline'''.stripMargin() + + println(triple) + } + + @Test + void 'striple single quoted with special characters'() { + def specialCharacters = '''hello \'John\'. This is backslash - \\. \nSecond line starts here''' + + println(specialCharacters) + } + +} diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy new file mode 100644 index 0000000000..85130e8f07 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy @@ -0,0 +1,114 @@ +package com.baeldung.traits + +import spock.lang.Specification + +class TraitsUnitTest extends Specification { + + Employee employee + Dog dog + + void setup () { + employee = new Employee() + dog = new Dog() + } + + def 'Should return msg string when using Employee.sayHello method provided by UserTrait' () { + when: + def msg = employee.sayHello() + then: + msg + msg instanceof String + assert msg == "Hello!" + } + + def 'Should return displayMsg string when using Employee.showName method' () { + when: + def displayMsg = employee.showName() + then: + displayMsg + displayMsg instanceof String + assert displayMsg == "Hello, Bob!" + } + + def 'Should return greetMsg string when using Employee.greet method' () { + when: + def greetMsg = employee.greet() + then: + greetMsg + greetMsg instanceof String + assert greetMsg == "Hello, from a private method!" + } + + def 'Should return MissingMethodException when using Employee.greetingMessage method' () { + when: + def exception + try { + employee.greetingMessage() + }catch(Exception e) { + exception = e + } + + then: + exception + exception instanceof groovy.lang.MissingMethodException + assert exception.message == "No signature of method: com.baeldung.traits.Employee.greetingMessage()"+ + " is applicable for argument types: () values: []" + } + + def 'Should return employee instance when using Employee.whoAmI method' () { + when: + def emp = employee.self() + then: + emp + emp instanceof Employee + assert emp.is(employee) + } + + def 'Should display lastName when using Employee.showLastName method' () { + when: + def lastNameMsg = employee.showLastName() + then: + lastNameMsg + lastNameMsg instanceof String + assert lastNameMsg == "Hello, Marley!" + } + + def 'Should be able to define properties of UserTrait in Employee instance' () { + when: + employee = new Employee(email: "a@e.com", address: "baeldung.com") + then: + employee + employee instanceof Employee + assert employee.email == "a@e.com" + assert employee.address == "baeldung.com" + } + + def 'Should execute basicAbility method from SpeakingTrait and return msg string' () { + when: + def speakMsg = dog.basicAbility() + then: + speakMsg + speakMsg instanceof String + assert speakMsg == "Speaking!!" + } + + def 'Should verify multiple inheritance with traits and execute overridden traits method' () { + when: + def walkSpeakMsg = dog.speakAndWalk() + println walkSpeakMsg + then: + walkSpeakMsg + walkSpeakMsg instanceof String + assert walkSpeakMsg == "Walk and speak!!" + } + + def 'Should implement AnimalTrait at runtime and access basicBehavior method' () { + when: + def dogInstance = new Dog() as AnimalTrait + def basicBehaviorMsg = dogInstance.basicBehavior() + then: + basicBehaviorMsg + basicBehaviorMsg instanceof String + assert basicBehaviorMsg == "Animalistic!!" + } +} \ No newline at end of file diff --git a/core-java-11/README.md b/core-java-11/README.md deleted file mode 100644 index 181ada3f45..0000000000 --- a/core-java-11/README.md +++ /dev/null @@ -1,5 +0,0 @@ -### Relevant articles - -- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code) -- [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params) - diff --git a/core-java-8/src/main/java/com/baeldung/Adder.java b/core-java-8/src/main/java/com/baeldung/Adder.java deleted file mode 100644 index e3e100f121..0000000000 --- a/core-java-8/src/main/java/com/baeldung/Adder.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung; - -import java.util.function.Consumer; -import java.util.function.Function; - -public interface Adder { - - String addWithFunction(Function f); - - void addWithConsumer(Consumer f); - -} diff --git a/core-java-8/src/main/java/com/baeldung/AdderImpl.java b/core-java-8/src/main/java/com/baeldung/AdderImpl.java deleted file mode 100644 index 7852934d55..0000000000 --- a/core-java-8/src/main/java/com/baeldung/AdderImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung; - - -import java.util.function.Consumer; -import java.util.function.Function; - -public class AdderImpl implements Adder { - - @Override - public String addWithFunction(final Function f) { - return f.apply("Something "); - } - - @Override - public void addWithConsumer(final Consumer f) { - } - -} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java deleted file mode 100644 index bf0e613567..0000000000 --- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.interfaces.polymorphysim; - -public class Circle implements Shape { - - private double radius; - - public Circle(double radius){ - this.radius = radius; - } - - @Override - public String name() { - return "Circle"; - } - - @Override - public double area() { - return Math.PI * (radius * radius); - } - -} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java deleted file mode 100644 index 2cf4fafee1..0000000000 --- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.interfaces.polymorphysim; - -import java.util.ArrayList; - -public class DisplayShape { - - private ArrayList shapes; - - public DisplayShape() { - shapes = new ArrayList<>(); - } - - public void add(Shape shape) { - shapes.add(shape); - } - - public void display() { - for (Shape shape : shapes) { - System.out.println(shape.name() + " area: " + shape.area()); - } - } -} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java deleted file mode 100644 index cc43c1300b..0000000000 --- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.interfaces.polymorphysim; - -public class MainPolymorphic { - public static void main(String[] args){ - - Shape circleShape = new Circle(2); - Shape squareShape = new Square(2); - - DisplayShape displayShape = new DisplayShape(); - displayShape.add(circleShape); - displayShape.add(squareShape); - - displayShape.display(); - } -} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java deleted file mode 100644 index 9c440150b5..0000000000 --- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.interfaces.polymorphysim; - -public class Square implements Shape { - - private double width; - - public Square(double width) { - this.width = width; - } - - @Override - public String name() { - return "Square"; - } - - @Override - public double area() { - return width * width; - } -} diff --git a/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java b/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java deleted file mode 100644 index 7ded5e6621..0000000000 --- a/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.interfaces; - -import com.baeldung.interfaces.polymorphysim.Circle; -import com.baeldung.interfaces.polymorphysim.Shape; -import com.baeldung.interfaces.polymorphysim.Square; -import org.assertj.core.api.Assertions; -import org.junit.Test; - -public class PolymorphysimUnitTest { - - @Test - public void whenInterfacePointsToCircle_CircleAreaMethodisBeingCalled(){ - double expectedArea = 12.566370614359172; - Shape circle = new Circle(2); - double actualArea = circle.area(); - Assertions.assertThat(actualArea).isEqualTo(expectedArea); - } - - @Test - public void whenInterfacePointsToSquare_SquareAreaMethodisBeingCalled(){ - double expectedArea = 4; - Shape square = new Square(2); - double actualArea = square.area(); - Assertions.assertThat(actualArea).isEqualTo(expectedArea); - } -} diff --git a/core-java-9/README.md b/core-java-9/README.md deleted file mode 100644 index 38816471aa..0000000000 --- a/core-java-9/README.md +++ /dev/null @@ -1,29 +0,0 @@ -========= - -## Core Java 9 Examples - -[Java 9 New Features](http://www.baeldung.com/new-java-9) - -### Relevant Articles: -- [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api) -- [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) -- [Spring Security – Redirect to the Previous URL After Login](http://www.baeldung.com/spring-security-redirect-login) -- [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) -- [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) -- [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) -- [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional) -- [Java 9 java.lang.Module API](http://www.baeldung.com/java-9-module-api) -- [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) diff --git a/core-java-arrays/README.MD b/core-java-arrays/README.MD new file mode 100644 index 0000000000..9ee6998784 --- /dev/null +++ b/core-java-arrays/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) diff --git a/core-java-arrays/src/main/java/com/baeldung/array/JaggedArray.java b/core-java-arrays/src/main/java/com/baeldung/array/JaggedArray.java deleted file mode 100644 index 36cfc88b95..0000000000 --- a/core-java-arrays/src/main/java/com/baeldung/array/JaggedArray.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.array; - -import java.util.Arrays; -import java.util.Scanner; - -public class JaggedArray { - - int[][] shortHandFormInitialization() { - int[][] jaggedArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; - return jaggedArr; - } - - int[][] declarationAndThenInitialization() { - int[][] jaggedArr = new int[3][]; - jaggedArr[0] = new int[] { 1, 2 }; - jaggedArr[1] = new int[] { 3, 4, 5 }; - jaggedArr[2] = new int[] { 6, 7, 8, 9 }; - return jaggedArr; - } - - int[][] declarationAndThenInitializationUsingUserInputs() { - int[][] jaggedArr = new int[3][]; - jaggedArr[0] = new int[2]; - jaggedArr[1] = new int[3]; - jaggedArr[2] = new int[4]; - initializeElements(jaggedArr); - return jaggedArr; - } - - void initializeElements(int[][] jaggedArr) { - Scanner sc = new Scanner(System.in); - for (int outer = 0; outer < jaggedArr.length; outer++) { - for (int inner = 0; inner < jaggedArr[outer].length; inner++) { - jaggedArr[outer][inner] = sc.nextInt(); - } - } - } - - void printElements(int[][] jaggedArr) { - for (int index = 0; index < jaggedArr.length; index++) { - System.out.println(Arrays.toString(jaggedArr[index])); - } - } - - int[] getElementAtGivenIndex(int[][] jaggedArr, int index) { - return jaggedArr[index]; - } - -} diff --git a/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java new file mode 100644 index 0000000000..26a4ca7ef4 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java @@ -0,0 +1,52 @@ +package com.baeldung.array.conversions; + +import java.util.Arrays; +import java.util.function.IntFunction; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class StreamArrayConversion { + + public static String[] stringStreamToStringArrayUsingFunctionalInterface(Stream stringStream) { + IntFunction intFunction = new IntFunction() { + @Override + public String[] apply(int value) { + return new String[value]; + } + }; + + return stringStream.toArray(intFunction); + } + + public static String[] stringStreamToStringArrayUsingMethodReference(Stream stringStream) { + return stringStream.toArray(String[]::new); + } + + public static String[] stringStreamToStringArrayUsingLambda(Stream stringStream) { + return stringStream.toArray(value -> new String[value]); + } + + public static Integer[] integerStreamToIntegerArray(Stream integerStream) { + return integerStream.toArray(Integer[]::new); + } + + public static int[] intStreamToPrimitiveIntArray(Stream integerStream) { + return integerStream.mapToInt(i -> i).toArray(); + } + + public static Stream stringArrayToStreamUsingArraysStream(String[] stringArray) { + return Arrays.stream(stringArray); + } + + public static Stream stringArrayToStreamUsingStreamOf(String[] stringArray) { + return Stream.of(stringArray); + } + + public static IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) { + return Arrays.stream(intArray); + } + + public static Stream primitiveIntArrayToStreamUsingStreamOf(int[] intArray) { + return Stream.of(intArray); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/JaggedArrayUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/JaggedArrayUnitTest.java deleted file mode 100644 index a4dd7e25c3..0000000000 --- a/core-java-arrays/src/test/java/com/baeldung/array/JaggedArrayUnitTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.baeldung.array; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.PrintStream; - -import org.junit.Test; - -public class JaggedArrayUnitTest { - - private JaggedArray obj = new JaggedArray(); - - @Test - public void whenInitializedUsingShortHandForm_thenCorrect() { - assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.shortHandFormInitialization()); - } - - @Test - public void whenInitializedWithDeclarationAndThenInitalization_thenCorrect() { - assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.declarationAndThenInitialization()); - } - - @Test - public void whenInitializedWithDeclarationAndThenInitalizationUsingUserInputs_thenCorrect() { - InputStream is = new ByteArrayInputStream("1 2 3 4 5 6 7 8 9".getBytes()); - System.setIn(is); - assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.declarationAndThenInitializationUsingUserInputs()); - System.setIn(System.in); - } - - @Test - public void givenJaggedArrayAndAnIndex_thenReturnArrayAtGivenIndex() { - int[][] jaggedArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; - assertArrayEquals(new int[] { 1, 2 }, obj.getElementAtGivenIndex(jaggedArr, 0)); - assertArrayEquals(new int[] { 3, 4, 5 }, obj.getElementAtGivenIndex(jaggedArr, 1)); - assertArrayEquals(new int[] { 6, 7, 8, 9 }, obj.getElementAtGivenIndex(jaggedArr, 2)); - } - - @Test - public void givenJaggedArray_whenUsingArraysAPI_thenVerifyPrintedElements() { - int[][] jaggedArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; - ByteArrayOutputStream outContent = new ByteArrayOutputStream(); - System.setOut(new PrintStream(outContent)); - obj.printElements(jaggedArr); - assertEquals("[1, 2][3, 4, 5][6, 7, 8, 9]", outContent.toString().replace("\r", "").replace("\n", "")); - System.setOut(System.out); - } - -} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java new file mode 100644 index 0000000000..d2173fea5b --- /dev/null +++ b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.array.conversions; + +import static com.baeldung.array.conversions.StreamArrayConversion.intStreamToPrimitiveIntArray; +import static com.baeldung.array.conversions.StreamArrayConversion.integerStreamToIntegerArray; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingFunctionalInterface; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingLambda; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingMethodReference; +import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingArraysStream; +import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingStreamOf; +import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingArraysStream; +import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingStreamOf; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Iterators; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.junit.Test; + +public class StreamArrayConversionUnitTest { + + private String[] stringArray = new String[]{"baeldung", "convert", "to", "string", "array"}; + private Integer[] integerArray = new Integer[]{1, 2, 3, 4, 5, 6, 7}; + private int[] intPrimitiveArray = new int[]{1, 2, 3, 4, 5, 6, 7}; + + @Test + public void givenStringStream_thenConvertToStringArrayUsingFunctionalInterface() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingFunctionalInterface(stringStream)); + } + + @Test + public void givenStringStream_thenConvertToStringArrayUsingMethodReference() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingMethodReference(stringStream)); + } + + @Test + public void givenStringStream_thenConvertToStringArrayUsingLambda() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingLambda(stringStream)); + } + + @Test + public void givenIntegerStream_thenConvertToIntegerArray() { + Stream integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7); + assertArrayEquals(integerArray, integerStreamToIntegerArray(integerStream)); + } + + @Test + public void givenIntStream_thenConvertToIntegerArray() { + Stream integerStream = IntStream.rangeClosed(1, 7).boxed(); + assertArrayEquals(intPrimitiveArray, intStreamToPrimitiveIntArray(integerStream)); + } + + @Test + public void givenStringArray_whenConvertedTwoWays_thenConvertedStreamsAreEqual() { + assertTrue(Iterators + .elementsEqual(stringArrayToStreamUsingArraysStream(stringArray).iterator(), + stringArrayToStreamUsingStreamOf(stringArray).iterator())); + } + + @Test + public void givenPrimitiveArray_whenConvertedTwoWays_thenConvertedStreamsAreNotEqual() { + assertFalse(Iterators.elementsEqual( + primitiveIntArrayToStreamUsingArraysStream(intPrimitiveArray).iterator(), + primitiveIntArrayToStreamUsingStreamOf(intPrimitiveArray).iterator())); + } +} diff --git a/core-java-collections/README.md b/core-java-collections/README.md deleted file mode 100644 index 4c0b24cd5d..0000000000 --- a/core-java-collections/README.md +++ /dev/null @@ -1,54 +0,0 @@ -========= - -## Core Java Collections Cookbooks and Examples - -### 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 - Combine Multiple Collections](http://www.baeldung.com/java-combine-multiple-collections) -- [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) -- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) -- [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset) -- [Collect a Java Stream to an Immutable Collection](http://www.baeldung.com/java-stream-immutable-collection) -- [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque) -- [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset) -- [A Guide to TreeSet in Java](http://www.baeldung.com/java-tree-set) -- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list) -- [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size) -- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards) -- [How to Filter a Collection in Java](http://www.baeldung.com/java-collection-filtering) -- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list) -- [Remove the First Element from a List](http://www.baeldung.com/java-remove-first-element-from-list) -- [Initializing HashSet at the Time of Construction](http://www.baeldung.com/java-initialize-hashset) -- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) -- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator) -- [Shuffling Collections In Java](http://www.baeldung.com/java-shuffle-collection) -- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java) -- [An Introduction to Java.util.Hashtable Class](http://www.baeldung.com/java-hash-table) -- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) -- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max) -- [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections) -- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list) -- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe) -- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list) -- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall) -- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance) -- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity) -- [Operating on and Removing an Item from Stream](https://www.baeldung.com/java-use-remove-item-stream) -- [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) -- [Guide to EnumSet](https://www.baeldung.com/java-enumset) -- [Removing Elements from Java Collections](https://www.baeldung.com/java-collection-remove-elements) -- [Converting a Collection to ArrayList in Java](https://www.baeldung.com/java-convert-collection-arraylist) -- [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items) -- [Combining Different Types of Collections in Java](https://www.baeldung.com/java-combine-collections) -- [Sorting in Java](http://www.baeldung.com/java-sorting) -- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist) -- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception) -- [Join and Split Arrays and Collections in Java](http://www.baeldung.com/java-join-and-split) -- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality) -- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line) -- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) -- [A Guide to EnumMap](https://www.baeldung.com/java-enum-map) -- [Ways to Iterate Over a List in Java](https://www.baeldung.com/java-iterate-list) diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java b/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java deleted file mode 100644 index 09ecebe47b..0000000000 --- a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.baeldung.java.collections; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.junit.Assert; -import org.junit.Test; - -class CollectionsEmpty { - - @Test - public void givenArrayList_whenAddingElement_addsNewElement() { - ArrayList mutableList = new ArrayList<>(); - mutableList.add("test"); - - Assert.assertEquals(mutableList.size(), 1); - Assert.assertEquals(mutableList.get(0), "test"); - } - - @Test(expected = UnsupportedOperationException.class) - public void givenCollectionsEmptyList_whenAddingElement_throwsUnsupportedOperationException() { - List immutableList = Collections.emptyList(); - immutableList.add("test"); - } - -} diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListJUnitTest.java b/core-java-collections/src/test/java/org/baeldung/java/lists/ListJUnitTest.java deleted file mode 100644 index 7dddf6c2ce..0000000000 --- a/core-java-collections/src/test/java/org/baeldung/java/lists/ListJUnitTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.baeldung.java.lists; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - -public class ListJUnitTest { - - private final List list1 = Arrays.asList("1", "2", "3", "4"); - private final List list2 = Arrays.asList("1", "2", "3", "4"); - private final List list3 = Arrays.asList("1", "2", "4", "3"); - - @Test - public void whenTestingForEquality_ShouldBeEqual() throws Exception { - Assert.assertEquals(list1, list2); - Assert.assertNotSame(list1, list2); - Assert.assertNotEquals(list1, list3); - } -} diff --git a/core-java-lambdas/README.md b/core-java-lambdas/README.md new file mode 100644 index 0000000000..5b94953e68 --- /dev/null +++ b/core-java-lambdas/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Java 9 java.lang.Module API](https://www.baeldung.com/java-lambda-effectively-final-local-variables) diff --git a/core-java-lang/pom.xml b/core-java-lang/pom.xml deleted file mode 100644 index 2f307859f1..0000000000 --- a/core-java-lang/pom.xml +++ /dev/null @@ -1,436 +0,0 @@ - - 4.0.0 - com.baeldung - core-java-lang - 0.1.0-SNAPSHOT - jar - core-java-lang - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.google.code.gson - gson - ${gson.version} - - - - log4j - log4j - ${log4j.version} - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - - - org.projectlombok - lombok - ${lombok.version} - provided - - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - org.springframework - spring-web - ${springframework.spring-web.version} - - - javax.mail - mail - ${javax.mail.version} - - - nl.jqno.equalsverifier - equalsverifier - ${equalsverifier.version} - test - - - - - core-java-lang - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*LiveTest.java - **/*IntegrationTest.java - **/*IntTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - - - org.apache.maven.plugins - maven-jar-plugin - ${maven-jar-plugin.version} - - - - true - libs/ - org.baeldung.executable.ExecutableMavenJar - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - ${project.basedir} - - - org.baeldung.executable.ExecutableMavenJar - - - - jar-with-dependencies - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - ${maven-shade-plugin.version} - - - - shade - - - true - - - org.baeldung.executable.ExecutableMavenJar - - - - - - - - - com.jolira - onejar-maven-plugin - ${onejar-maven-plugin.version} - - - - org.baeldung.executable.ExecutableMavenJar - true - ${project.build.finalName}-onejar.${project.packaging} - - - one-jar - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-maven-plugin.version} - - - - repackage - - - spring-boot - org.baeldung.executable.ExecutableMavenJar - - - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - java - com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed - - -Xmx300m - -XX:+UseParallelGC - -classpath - - com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin.version} - - 1.8 - 1.8 - - - - - - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*ManualTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - - - json - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - run-benchmarks - - none - - exec - - - test - java - - -classpath - - org.openjdk.jmh.Main - .* - - - - - - - - - - - - buildAgentLoader - - - - org.apache.maven.plugins - maven-jar-plugin - - - package - - jar - - - agentLoader - target/classes - - - true - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - com/baeldung/instrumentation/application/AgentLoader.class - com/baeldung/instrumentation/application/Launcher.class - - - - - - - - - - buildApplication - - - - org.apache.maven.plugins - maven-jar-plugin - - - package - - jar - - - application - target/classes - - - true - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - com/baeldung/instrumentation/application/MyAtm.class - com/baeldung/instrumentation/application/MyAtmApplication.class - com/baeldung/instrumentation/application/Launcher.class - - - - - - - - - - buildAgent - - - - org.apache.maven.plugins - maven-jar-plugin - - - package - - jar - - - agent - target/classes - - - true - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - com/baeldung/instrumentation/agent/AtmTransformer.class - com/baeldung/instrumentation/agent/MyInstrumentationAgent.class - - - - - - - - - - - - - - 2.8.5 - 2.8.2 - - - 3.5 - 1.16.12 - - 1.5.0-b01 - - - 3.10.0 - - - 2.21.0 - 4.3.4.RELEASE - 3.0.0-M1 - 3.0.2 - 1.4.4 - 3.1.1 - 2.0.3.RELEASE - 1.6.0 - 3.0.3 - - - diff --git a/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java b/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java deleted file mode 100644 index 83f2a27ea7..0000000000 --- a/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.controlstructures; - -public class Loops { - - /** - * Dummy method. Only prints a generic message. - */ - private static void methodToRepeat() { - System.out.println("Dummy method."); - } - - /** - * Shows how to iterate 50 times with 3 different method/control structures. - */ - public static void repetitionTo50Examples() { - for (int i = 1; i <= 50; i++) { - methodToRepeat(); - } - - int whileCounter = 1; - while (whileCounter <= 50) { - methodToRepeat(); - whileCounter++; - } - - int count = 1; - do { - methodToRepeat(); - count++; - } while (count < 50); - } - - /** - * Prints text an N amount of times. Shows usage of the {@code break} branching statement. - * @param textToPrint Text to repeatedly print. - * @param times Amount to times to print received text. - */ - public static void printTextNTimes(String textToPrint, int times) { - int counter = 1; - while (true) { - System.out.println(textToPrint); - if (counter == times) { - break; - } - } - } - - /** - * Prints an specified amount of even numbers. Shows usage of both {@code break} and {@code continue} branching statements. - * @param amountToPrint Amount of even numbers to print. - */ - public static void printEvenNumbers(int amountToPrint) { - if (amountToPrint <= 0) { // Invalid input - return; - } - int iterator = 0; - int amountPrinted = 0; - while (true) { - if (iterator % 2 == 0) { // Is an even number - System.out.println(iterator); - amountPrinted++; - iterator++; - } else { - iterator++; - continue; // Won't print - } - if (amountPrinted == amountToPrint) { - break; - } - } - } - -} diff --git a/core-java-lang/src/main/java/com/baeldung/enums/README.md b/core-java-lang/src/main/java/com/baeldung/enums/README.md deleted file mode 100644 index 6ccfa725f5..0000000000 --- a/core-java-lang/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) diff --git a/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java b/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java deleted file mode 100644 index 2d874fa650..0000000000 --- a/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.java.enumiteration; - -import java.util.EnumSet; - -public class EnumIterationExamples { - public static void main(String[] args) { - System.out.println("Enum iteration using forEach:"); - EnumSet.allOf(DaysOfWeekEnum.class).forEach(day -> System.out.println(day)); - - System.out.println("Enum iteration using Stream:"); - DaysOfWeekEnum.stream().filter(d -> d.getTypeOfDay().equals("off")).forEach(System.out::println); - - System.out.println("Enum iteration using for loop:"); - for (DaysOfWeekEnum day : DaysOfWeekEnum.values()) { - System.out.println(day); - } - } -} diff --git a/core-java-modules/README.md b/core-java-modules/README.md new file mode 100644 index 0000000000..9ce6057f32 --- /dev/null +++ b/core-java-modules/README.md @@ -0,0 +1,6 @@ +## Relevant articles: + +- [Multi-Module Maven Application with Java Modules](https://www.baeldung.com/maven-multi-module-project-java-jpms) +- [Guide to Java FileChannel](https://www.baeldung.com/java-filechannel) +- [Understanding the NumberFormatException in Java](https://www.baeldung.com/java-number-format-exception) +- [Will an Error Be Caught by Catch Block in Java?](https://www.baeldung.com/java-error-catch) diff --git a/core-java-10/README.md b/core-java-modules/core-java-10/README.md similarity index 85% rename from core-java-10/README.md rename to core-java-modules/core-java-10/README.md index f0a25712a7..8fb4f8a7dd 100644 --- a/core-java-10/README.md +++ b/core-java-modules/core-java-10/README.md @@ -5,3 +5,4 @@ - [Guide to Java 10](http://www.baeldung.com/java-10-overview) - [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) - [Deep Dive Into the New Java JIT Compiler – Graal](https://www.baeldung.com/graal-java-jit-compiler) +- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets) diff --git a/core-java-10/pom.xml b/core-java-modules/core-java-10/pom.xml similarity index 96% rename from core-java-10/pom.xml rename to core-java-modules/core-java-10/pom.xml index 9fcdd9a162..7163619679 100644 --- a/core-java-10/pom.xml +++ b/core-java-modules/core-java-10/pom.xml @@ -3,15 +3,16 @@ 4.0.0 com.baeldung core-java-10 - jar 0.1.0-SNAPSHOT core-java-10 + jar http://maven.apache.org com.baeldung parent-modules 1.0.0-SNAPSHOT + ../../ diff --git a/core-java-10/src/main/java/com/baeldung/App.java b/core-java-modules/core-java-10/src/main/java/com/baeldung/App.java similarity index 100% rename from core-java-10/src/main/java/com/baeldung/App.java rename to core-java-modules/core-java-10/src/main/java/com/baeldung/App.java diff --git a/core-java-10/src/main/java/com/baeldung/graal/CountUppercase.java b/core-java-modules/core-java-10/src/main/java/com/baeldung/graal/CountUppercase.java similarity index 100% rename from core-java-10/src/main/java/com/baeldung/graal/CountUppercase.java rename to core-java-modules/core-java-10/src/main/java/com/baeldung/graal/CountUppercase.java diff --git a/core-java-modules/core-java-10/src/main/java/com/baeldung/set/CopySets.java b/core-java-modules/core-java-10/src/main/java/com/baeldung/set/CopySets.java new file mode 100644 index 0000000000..d49724f81d --- /dev/null +++ b/core-java-modules/core-java-10/src/main/java/com/baeldung/set/CopySets.java @@ -0,0 +1,13 @@ +package com.baeldung.set; + +import java.util.Set; + +public class CopySets { + + // Using Java 10 + public static Set copyBySetCopyOf(Set original) { + Set copy = Set.copyOf(original); + return copy; + } + +} diff --git a/core-java-11/src/main/resources/logback.xml b/core-java-modules/core-java-10/src/main/resources/logback.xml similarity index 100% rename from core-java-11/src/main/resources/logback.xml rename to core-java-modules/core-java-10/src/main/resources/logback.xml diff --git a/core-java-10/src/test/java/com/baeldung/AppTest.java b/core-java-modules/core-java-10/src/test/java/com/baeldung/AppTest.java similarity index 100% rename from core-java-10/src/test/java/com/baeldung/AppTest.java rename to core-java-modules/core-java-10/src/test/java/com/baeldung/AppTest.java diff --git a/core-java-10/src/test/java/com/baeldung/java10/Java10FeaturesUnitTest.java b/core-java-modules/core-java-10/src/test/java/com/baeldung/java10/Java10FeaturesUnitTest.java similarity index 100% rename from core-java-10/src/test/java/com/baeldung/java10/Java10FeaturesUnitTest.java rename to core-java-modules/core-java-10/src/test/java/com/baeldung/java10/Java10FeaturesUnitTest.java diff --git a/core-java-10/src/test/java/com/baeldung/java10/list/CopyListServiceUnitTest.java b/core-java-modules/core-java-10/src/test/java/com/baeldung/java10/list/CopyListServiceUnitTest.java similarity index 100% rename from core-java-10/src/test/java/com/baeldung/java10/list/CopyListServiceUnitTest.java rename to core-java-modules/core-java-10/src/test/java/com/baeldung/java10/list/CopyListServiceUnitTest.java diff --git a/core-java-modules/core-java-11/README.md b/core-java-modules/core-java-11/README.md new file mode 100644 index 0000000000..11c7d9d388 --- /dev/null +++ b/core-java-modules/core-java-11/README.md @@ -0,0 +1,11 @@ +### Relevant articles + +- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code) +- [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) +- [An Introduction to Epsilon GC: A No-Op Experimental Garbage Collector](https://www.baeldung.com/jvm-epsilon-gc-garbage-collector) +- [Guide to jlink](https://www.baeldung.com/jlink) +- [Negate a Predicate Method Reference with Java 11](https://www.baeldung.com/java-negate-predicate-method-reference) +- [Transforming an Empty String into an Empty Optional](https://www.baeldung.com/java-empty-string-to-empty-optional) diff --git a/core-java-11/pom.xml b/core-java-modules/core-java-11/pom.xml similarity index 57% rename from core-java-11/pom.xml rename to core-java-modules/core-java-11/pom.xml index 4dcab49867..4d950bdf8d 100644 --- a/core-java-11/pom.xml +++ b/core-java-modules/core-java-11/pom.xml @@ -1,19 +1,36 @@ - + 4.0.0 com.baeldung core-java-11 - jar 0.1.0-SNAPSHOT core-java-11 + jar http://maven.apache.org com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. + + + com.google.guava + guava + ${guava.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + @@ -31,6 +48,8 @@ 11 11 + 27.1-jre + 3.11.1 diff --git a/core-java-11/src/main/java/com/baeldung/App.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/App.java similarity index 100% rename from core-java-11/src/main/java/com/baeldung/App.java rename to core-java-modules/core-java-11/src/main/java/com/baeldung/App.java diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/Outer.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/Outer.java new file mode 100644 index 0000000000..1d3cd72b44 --- /dev/null +++ b/core-java-modules/core-java-11/src/main/java/com/baeldung/Outer.java @@ -0,0 +1,24 @@ +package com.baeldung; + +import java.lang.reflect.Method; + +public class Outer { + + public void outerPublic() { + } + + private void outerPrivate() { + } + + class Inner { + + public void innerPublic() { + outerPrivate(); + } + + public void innerPublicReflection(Outer ob) throws Exception { + Method method = ob.getClass().getDeclaredMethod("outerPrivate"); + method.invoke(ob); + } + } +} \ No newline at end of file diff --git a/core-java-11/src/main/java/com/baeldung/add b/core-java-modules/core-java-11/src/main/java/com/baeldung/add old mode 100755 new mode 100644 similarity index 100% rename from core-java-11/src/main/java/com/baeldung/add rename to core-java-modules/core-java-11/src/main/java/com/baeldung/add diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java new file mode 100644 index 0000000000..97e216513b --- /dev/null +++ b/core-java-modules/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"); + } + +} diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java new file mode 100644 index 0000000000..725f969596 --- /dev/null +++ b/core-java-modules/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java @@ -0,0 +1,132 @@ +/* + * 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.java11.httpclient; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpClient.Version; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.net.http.HttpResponse.PushPromiseHandler; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class HttpClientExample { + + public static void main(String[] args) throws Exception { + httpGetRequest(); + httpPostRequest(); + asynchronousGetRequest(); + asynchronousMultipleRequests(); + pushRequest(); + } + + public static void httpGetRequest() throws URISyntaxException, IOException, InterruptedException { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .version(HttpClient.Version.HTTP_2) + .uri(URI.create("http://jsonplaceholder.typicode.com/posts/1")) + .headers("Accept-Enconding", "gzip, deflate") + .build(); + HttpResponse response = client.send(request, BodyHandlers.ofString()); + + String responseBody = response.body(); + int responseStatusCode = response.statusCode(); + + System.out.println("httpGetRequest: " + responseBody); + System.out.println("httpGetRequest status code: " + responseStatusCode); + } + + public static void httpPostRequest() throws URISyntaxException, IOException, InterruptedException { + HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .build(); + HttpRequest request = HttpRequest.newBuilder(new URI("http://jsonplaceholder.typicode.com/posts")) + .version(HttpClient.Version.HTTP_2) + .POST(BodyPublishers.ofString("Sample Post Request")) + .build(); + HttpResponse response = client.send(request, BodyHandlers.ofString()); + String responseBody = response.body(); + System.out.println("httpPostRequest : " + responseBody); + } + + public static void asynchronousGetRequest() throws URISyntaxException { + HttpClient client = HttpClient.newHttpClient(); + URI httpURI = new URI("http://jsonplaceholder.typicode.com/posts/1"); + HttpRequest request = HttpRequest.newBuilder(httpURI) + .version(HttpClient.Version.HTTP_2) + .build(); + CompletableFuture futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenAccept(resp -> { + System.out.println("Got pushed response " + resp.uri()); + System.out.println("Response statuscode: " + resp.statusCode()); + System.out.println("Response body: " + resp.body()); + }); + System.out.println("futureResponse" + futureResponse); + + } + + public static void asynchronousMultipleRequests() throws URISyntaxException { + HttpClient client = HttpClient.newHttpClient(); + List uris = Arrays.asList(new URI("http://jsonplaceholder.typicode.com/posts/1"), new URI("http://jsonplaceholder.typicode.com/posts/2")); + List requests = uris.stream() + .map(HttpRequest::newBuilder) + .map(reqBuilder -> reqBuilder.build()) + .collect(Collectors.toList()); + System.out.println("Got pushed response1 " + requests); + CompletableFuture.allOf(requests.stream() + .map(request -> client.sendAsync(request, BodyHandlers.ofString())) + .toArray(CompletableFuture[]::new)) + .thenAccept(System.out::println) + .join(); + } + + public static void pushRequest() throws URISyntaxException, InterruptedException { + System.out.println("Running HTTP/2 Server Push example..."); + + HttpClient httpClient = HttpClient.newBuilder() + .version(Version.HTTP_2) + .build(); + + HttpRequest pageRequest = HttpRequest.newBuilder() + .uri(URI.create("https://http2.golang.org/serverpush")) + .build(); + + // Interface HttpResponse.PushPromiseHandler + // void applyPushPromise​(HttpRequest initiatingRequest, HttpRequest pushPromiseRequest, Function,​CompletableFuture>> acceptor) + httpClient.sendAsync(pageRequest, BodyHandlers.ofString(), pushPromiseHandler()) + .thenAccept(pageResponse -> { + System.out.println("Page response status code: " + pageResponse.statusCode()); + System.out.println("Page response headers: " + pageResponse.headers()); + String responseBody = pageResponse.body(); + System.out.println(responseBody); + }).join(); + + Thread.sleep(1000); // waiting for full response + } + + private static PushPromiseHandler pushPromiseHandler() { + return (HttpRequest initiatingRequest, + HttpRequest pushPromiseRequest, + Function, + CompletableFuture>> acceptor) -> { + acceptor.apply(BodyHandlers.ofString()) + .thenAccept(resp -> { + System.out.println(" Pushed response: " + resp.uri() + ", headers: " + resp.headers()); + }); + System.out.println("Promise request: " + pushPromiseRequest.uri()); + System.out.println("Promise request: " + pushPromiseRequest.headers()); + }; + } + +} diff --git a/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java b/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java new file mode 100644 index 0000000000..3c93e08194 --- /dev/null +++ b/core-java-modules/core-java-11/src/main/java/com/baeldung/predicate/not/Person.java @@ -0,0 +1,19 @@ +package com.baeldung.predicate.not; + +public class Person { + private static final int ADULT_AGE = 18; + + private int age; + + public Person(int age) { + this.age = age; + } + + public boolean isAdult() { + return age >= ADULT_AGE; + } + + public boolean isNotAdult() { + return !isAdult(); + } +} diff --git a/core-java-8/src/main/resources/logback.xml b/core-java-modules/core-java-11/src/main/resources/logback.xml similarity index 100% rename from core-java-8/src/main/resources/logback.xml rename to core-java-modules/core-java-11/src/main/resources/logback.xml diff --git a/core-java-modules/core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java b/core-java-modules/core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java new file mode 100644 index 0000000000..47fe62ba40 --- /dev/null +++ b/core-java-modules/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-modules/core-java-11/src/modules/jlinkModule/module-info.java b/core-java-modules/core-java-11/src/modules/jlinkModule/module-info.java new file mode 100644 index 0000000000..0587c65b53 --- /dev/null +++ b/core-java-modules/core-java-11/src/modules/jlinkModule/module-info.java @@ -0,0 +1,3 @@ +module jlinkModule { + requires java.logging; +} \ No newline at end of file diff --git a/core-java-11/src/test/java/com/baeldung/AppTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java similarity index 82% rename from core-java-11/src/test/java/com/baeldung/AppTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java index c9f61455bd..73eb8e661a 100644 --- a/core-java-11/src/test/java/com/baeldung/AppTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/AppUnitTest.java @@ -7,7 +7,7 @@ import junit.framework.TestSuite; /** * Unit test for simple App. */ -public class AppTest +public class AppUnitTest extends TestCase { /** @@ -15,7 +15,7 @@ public class AppTest * * @param testName name of the test case */ - public AppTest( String testName ) + public AppUnitTest(String testName ) { super( testName ); } @@ -25,7 +25,7 @@ public class AppTest */ public static Test suite() { - return new TestSuite( AppTest.class ); + return new TestSuite( AppUnitTest.class ); } /** diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/EmptyStringToEmptyOptionalUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/EmptyStringToEmptyOptionalUnitTest.java new file mode 100644 index 0000000000..cc429209d4 --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/EmptyStringToEmptyOptionalUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung; + +import com.google.common.base.Strings; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Optional; +import java.util.function.Predicate; + +public class EmptyStringToEmptyOptionalUnitTest { + + @Test + public void givenEmptyString_whenFilteringOnOptional_thenEmptyOptionalIsReturned() { + String str = ""; + Optional opt = Optional.ofNullable(str).filter(s -> !s.isEmpty()); + Assert.assertFalse(opt.isPresent()); + } + + @Test + public void givenEmptyString_whenFilteringOnOptionalInJava11_thenEmptyOptionalIsReturned() { + String str = ""; + Optional opt = Optional.ofNullable(str).filter(Predicate.not(String::isEmpty)); + Assert.assertFalse(opt.isPresent()); + } + + @Test + public void givenEmptyString_whenPassingResultOfEmptyToNullToOfNullable_thenEmptyOptionalIsReturned() { + String str = ""; + Optional opt = Optional.ofNullable(Strings.emptyToNull(str)); + Assert.assertFalse(opt.isPresent()); + } +} diff --git a/core-java-11/src/test/java/com/baeldung/NewStringAPIUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/NewStringAPIUnitTest.java similarity index 100% rename from core-java-11/src/test/java/com/baeldung/NewStringAPIUnitTest.java rename to core-java-modules/core-java-11/src/test/java/com/baeldung/NewStringAPIUnitTest.java diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java new file mode 100644 index 0000000000..9e6bd72680 --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung; + +import static org.junit.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.is; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; +import org.junit.Test; + +public class OuterUnitTest { + + private static final String NEST_HOST_NAME = "com.baeldung.Outer"; + + @Test + public void whenGetNestHostFromOuter_thenGetNestHost() { + is(Outer.class.getNestHost().getName()).equals(NEST_HOST_NAME); + } + + @Test + public void whenGetNestHostFromInner_thenGetNestHost() { + is(Outer.Inner.class.getNestHost().getName()).equals(NEST_HOST_NAME); + } + + @Test + public void whenCheckNestmatesForNestedClasses_thenGetTrue() { + is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(true); + } + + @Test + public void whenCheckNestmatesForUnrelatedClasses_thenGetFalse() { + is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(false); + } + + @Test + public void whenGetNestMembersForNestedClasses_thenGetAllNestedClasses() { + Set nestMembers = Arrays.stream(Outer.Inner.class.getNestMembers()) + .map(Class::getName) + .collect(Collectors.toSet()); + + is(nestMembers.size()).equals(2); + + assertTrue(nestMembers.contains("com.baeldung.Outer")); + assertTrue(nestMembers.contains("com.baeldung.Outer$Inner")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java new file mode 100644 index 0000000000..42f56838c4 --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java @@ -0,0 +1,240 @@ +package com.baeldung.java11.httpclient.test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; +import java.net.ProxySelector; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +public class HttpClientUnitTest { + + @Test + public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofString("Sample body")) + .build(); + + + HttpResponse response = HttpClient.newBuilder() + .proxy(ProxySelector.getDefault()) + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample body")); + } + + @Test + public void shouldNotFollowRedirectWhenSetToDefaultNever() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_1_1) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM)); + assertThat(response.body(), containsString("https://stackoverflow.com/")); + } + + @Test + public void shouldFollowRedirectWhenSetToAlways() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_1_1) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.request() + .uri() + .toString(), equalTo("https://stackoverflow.com/")); + } + + @Test + public void shouldReturnOKStatusForAuthenticatedAccess() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/basic-auth")) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("postman", "password".toCharArray()); + } + }) + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldSendRequestAsync() throws URISyntaxException, InterruptedException, ExecutionException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofString("Sample body")) + .build(); + CompletableFuture> response = HttpClient.newBuilder() + .build() + .sendAsync(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldUseJustTwoThreadWhenProcessingSendAsyncRequest() throws URISyntaxException, InterruptedException, ExecutionException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + ExecutorService executorService = Executors.newFixedThreadPool(2); + + CompletableFuture> response1 = HttpClient.newBuilder() + .executor(executorService) + .build() + .sendAsync(request, HttpResponse.BodyHandlers.ofString()); + + CompletableFuture> response2 = HttpClient.newBuilder() + .executor(executorService) + .build() + .sendAsync(request, HttpResponse.BodyHandlers.ofString()); + + CompletableFuture> response3 = HttpClient.newBuilder() + .executor(executorService) + .build() + .sendAsync(request, HttpResponse.BodyHandlers.ofString()); + + CompletableFuture.allOf(response1, response2, response3) + .join(); + + assertThat(response1.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response2.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response3.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldNotStoreCookieWhenPolicyAcceptNone() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpClient httpClient = HttpClient.newBuilder() + .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_NONE)) + .build(); + + httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + assertTrue(httpClient.cookieHandler() + .isPresent()); + } + + @Test + public void shouldStoreCookieWhenPolicyAcceptAll() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpClient httpClient = HttpClient.newBuilder() + .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL)) + .build(); + + httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + assertTrue(httpClient.cookieHandler() + .isPresent()); + } + + @Test + public void shouldProcessMultipleRequestViaStream() throws URISyntaxException, ExecutionException, InterruptedException { + List targets = Arrays.asList(new URI("https://postman-echo.com/get?foo1=bar1"), new URI("https://postman-echo.com/get?foo2=bar2")); + + HttpClient client = HttpClient.newHttpClient(); + + List> futures = targets.stream() + .map(target -> client.sendAsync(HttpRequest.newBuilder(target) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()) + .thenApply(response -> response.body())) + .collect(Collectors.toList()); + + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + if (futures.get(0) + .get() + .contains("foo1")) { + assertThat(futures.get(0) + .get(), containsString("bar1")); + assertThat(futures.get(1) + .get(), containsString("bar2")); + } else { + assertThat(futures.get(1) + .get(), containsString("bar2")); + assertThat(futures.get(1) + .get(), containsString("bar1")); + } + + } + + @Test + public void completeExceptionallyExample() { + CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(String::toUpperCase, + CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS)); + CompletableFuture exceptionHandler = cf.handle((s, th) -> { return (th != null) ? "message upon cancel" : ""; }); + cf.completeExceptionally(new RuntimeException("completed exceptionally")); + assertTrue("Was not completed exceptionally", cf.isCompletedExceptionally()); + try { + cf.join(); + fail("Should have thrown an exception"); + } catch (CompletionException ex) { // just for testing + assertEquals("completed exceptionally", ex.getCause().getMessage()); + } + + assertEquals("message upon cancel", exceptionHandler.join()); + } + +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java new file mode 100644 index 0000000000..b87e6b3c6e --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java @@ -0,0 +1,168 @@ +package com.baeldung.java11.httpclient.test; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; + +import org.junit.Test; + +public class HttpRequestUnitTest { + + @Test + public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldUseHttp2WhenWebsiteUsesHttp2() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://stackoverflow.com")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2)); + } + + @Test + public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1)); + } + + @Test + public void shouldReturnStatusOKWhenSendGetRequestWithDummyHeaders() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .headers("key1", "value1", "key2", "value2") + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnStatusOKWhenSendGetRequestTimeoutSet() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .timeout(Duration.of(10, SECONDS)) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnNoContentWhenPostWithNoBody() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .POST(HttpRequest.BodyPublishers.noBody()) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithBodyText() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofString("Sample request body")) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithInputStream() throws IOException, InterruptedException, URISyntaxException { + byte[] sampleData = "Sample request body".getBytes(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(sampleData))) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithByteArrayProcessorStream() throws IOException, InterruptedException, URISyntaxException { + byte[] sampleData = "Sample request body".getBytes(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofByteArray(sampleData)) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithFileProcessorStream() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("src/test/resources/sample.txt"))) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample file content")); + } + +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java new file mode 100644 index 0000000000..a5cfc3f6b1 --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.java11.httpclient.test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import org.junit.Test; + +public class HttpResponseUnitTest { + + @Test + public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.NORMAL) + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertNotNull(response.body()); + } + + @Test + public void shouldResponseURIDifferentThanRequestUIRWhenRedirect() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.NORMAL) + .build() + .send(request, HttpResponse.BodyHandlers.ofString()); + + assertThat(request.uri() + .toString(), equalTo("http://stackoverflow.com")); + assertThat(response.uri() + .toString(), equalTo("https://stackoverflow.com/")); + } + +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java new file mode 100644 index 0000000000..281155138d --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.optional; + +import org.junit.Test; + +import java.util.Optional; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests for {@link Optional} in Java 11. + */ +public class OptionalUnitTest { + + @Test + public void givenAnEmptyOptional_isEmpty_thenBehavesAsExpected() { + Optional opt = Optional.of("Baeldung"); + assertFalse(opt.isEmpty()); + + opt = Optional.ofNullable(null); + assertTrue(opt.isEmpty()); + } +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java new file mode 100644 index 0000000000..a4989287be --- /dev/null +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/predicate/not/PersonUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.predicate.not; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.function.Predicate.not; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class PersonUnitTest { + private List people; + + @BeforeEach + void preparePeople() { + people = Arrays.asList( + new Person(1), + new Person(18), + new Person(2) + ); + } + + @Test + void givenPeople_whenFilterIsAdult_thenOneResult() { + List adults = people.stream() + .filter(Person::isAdult) + .collect(Collectors.toList()); + + assertThat(adults).size().isEqualTo(1); + } + + @Test + void givenPeople_whenFilterIsAdultNegated_thenTwoResults() { + List nonAdults = people.stream() + .filter(person -> !person.isAdult()) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } + + @Test + void givenPeople_whenFilterIsNotAdult_thenTwoResults() { + List nonAdults = people.stream() + .filter(Person::isNotAdult) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } + + @Test + void givenPeople_whenFilterNotIsAdult_thenTwoResults() { + List nonAdults = people.stream() + .filter(not(Person::isAdult)) + .collect(Collectors.toList()); + + assertThat(nonAdults).size().isEqualTo(2); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-12/pom.xml b/core-java-modules/core-java-12/pom.xml new file mode 100644 index 0000000000..06c49a0021 --- /dev/null +++ b/core-java-modules/core-java-12/pom.xml @@ -0,0 +1,50 @@ + + + 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} + --enable-preview + + + + + + + 12 + 12 + 3.6.1 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java new file mode 100644 index 0000000000..7c4cb9e8f0 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java @@ -0,0 +1,71 @@ +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/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java new file mode 100644 index 0000000000..3d80a36bf6 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/string/StringAPITest.java @@ -0,0 +1,43 @@ +package com.baeldung.string; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Test; + +public class StringAPITest { + + @Test + public void whenPositiveArgument_thenReturnIndentedString() { + String multilineStr = "This is\na multiline\nstring."; + String outputStr = " This is\n a multiline\n string.\n"; + + String postIndent = multilineStr.indent(3); + + assertThat(postIndent, equalTo(outputStr)); + } + + @Test + public void whenNegativeArgument_thenReturnReducedIndentedString() { + String multilineStr = " This is\n a multiline\n string."; + String outputStr = " This is\n a multiline\n string.\n"; + + String postIndent = multilineStr.indent(-2); + + assertThat(postIndent, equalTo(outputStr)); + } + + @Test + public void whenTransformUsingLamda_thenReturnTransformedString() { + String result = "hello".transform(input -> input + " world!"); + + assertThat(result, equalTo("hello world!")); + } + + @Test + public void whenTransformUsingParseInt_thenReturnInt() { + int result = "42".transform(Integer::parseInt); + + assertThat(result, equalTo(42)); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/switchExpression/SwitchUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/switchExpression/SwitchUnitTest.java new file mode 100644 index 0000000000..708e416090 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/switchExpression/SwitchUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.switchExpression; + +import org.junit.Assert; +import org.junit.Test; + +public class SwitchUnitTest { + + @Test + public void switchJava12(){ + + var month = Month.AUG; + + var value = switch(month){ + case JAN,JUN, JUL -> 3; + case FEB,SEP, OCT, NOV, DEC -> 1; + case MAR,MAY, APR, AUG -> 2; + }; + + Assert.assertEquals(value, 2); + } + + @Test + public void switchLocalVariable(){ + var month = Month.AUG; + int i = switch (month){ + case JAN,JUN, JUL -> 3; + case FEB,SEP, OCT, NOV, DEC -> 1; + case MAR,MAY, APR, AUG -> { + int j = month.toString().length() * 4; + break j; + } + }; + Assert.assertEquals(12, i); + } + + enum Month {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC} +} diff --git a/core-java-arrays/.gitignore b/core-java-modules/core-java-8-2/.gitignore similarity index 100% rename from core-java-arrays/.gitignore rename to core-java-modules/core-java-8-2/.gitignore diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md new file mode 100644 index 0000000000..245fa93ba7 --- /dev/null +++ b/core-java-modules/core-java-8-2/README.md @@ -0,0 +1,9 @@ +========= + +## Core Java 8 Cookbooks and Examples (part 2) + +### Relevant Articles: +- [Anonymous Classes in Java](http://www.baeldung.com/) +- [How to Delay Code Execution in Java](https://www.baeldung.com/java-delay-code-execution) +- [Run JAR Application With Command Line Arguments](https://www.baeldung.com/java-run-jar-with-arguments) +- [Java 8 Stream skip() vs limit()](https://www.baeldung.com/java-stream-skip-vs-limit) diff --git a/core-java-modules/core-java-8-2/pom.xml b/core-java-modules/core-java-8-2/pom.xml new file mode 100644 index 0000000000..07bb3b7543 --- /dev/null +++ b/core-java-modules/core-java-8-2/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + com.baeldung + core-java-8-2 + 0.1.0-SNAPSHOT + core-java-8-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + com.ibm.icu + icu4j + ${icu.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + UTF-8 + 1.8 + 1.8 + 64.2 + 3.12.2 + + diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/forEach/ReverseList.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/forEach/ReverseList.java new file mode 100644 index 0000000000..b2ce77a9f6 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/forEach/ReverseList.java @@ -0,0 +1,84 @@ +package com.baeldung.forEach; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.function.Consumer; + +class ReverseList extends ArrayList { + + List list = Arrays.asList("A", "B", "C", "D"); + + Consumer removeElement = s -> { + System.out.println(s + " " + list.size()); + if (s != null && s.equals("A")) { + list.remove("D"); + } + }; + + @Override + public Iterator iterator() { + + final int startIndex = this.size() - 1; + final List list = this; + return new Iterator() { + + int currentIndex = startIndex; + + @Override + public boolean hasNext() { + return currentIndex >= 0; + } + + @Override + public String next() { + String next = list.get(currentIndex); + currentIndex--; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public void forEach(Consumer action) { + for (String s : this) { + action.accept(s); + } + } + + public void iterateParallel() { + list.forEach(System.out::print); + System.out.print(" "); + list.parallelStream().forEach(System.out::print); + } + + public void iterateReverse() { + List myList = new ReverseList(); + myList.addAll(list); + myList.forEach(System.out::print); + System.out.print(" "); + myList.stream().forEach(System.out::print); + } + + public void removeInCollectionForEach() { + list.forEach(removeElement); + } + + public void removeInStreamForEach() { + list.stream().forEach(removeElement); + } + + public static void main(String[] argv) { + + ReverseList collectionForEach = new ReverseList(); + collectionForEach.iterateParallel(); + collectionForEach.iterateReverse(); + collectionForEach.removeInCollectionForEach(); + collectionForEach.removeInStreamForEach(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/jarArguments/JarExample.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/jarArguments/JarExample.java new file mode 100644 index 0000000000..c2fb809790 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/jarArguments/JarExample.java @@ -0,0 +1,18 @@ +package com.baeldung.jarArguments; + +public class JarExample { + + public static void main(String[] args) { + System.out.println("Hello Baeldung Reader in JarExample!"); + + if(args == null) { + System.out.println("You have not provided any arguments!"); + }else { + System.out.println("There are "+args.length+" argument(s)!"); + for(int i=0; i locales = Arrays.asList(new Locale[] { Locale.UK, Locale.ITALY, Locale.FRANCE, Locale.forLanguageTag("pl-PL") }); + Localization.run(locales); + JavaSEFormat.run(locales); + ICUFormat.run(locales); + } + +} diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/ICUFormat.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/ICUFormat.java new file mode 100644 index 0000000000..f7bc357933 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/ICUFormat.java @@ -0,0 +1,29 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import com.ibm.icu.text.MessageFormat; + +public class ICUFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + String format = bundle.getString("label-icu"); + MessageFormat formatter = new MessageFormat(format, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("ICU formatter"); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 3 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 3 }))); + } +} diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/JavaSEFormat.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/JavaSEFormat.java new file mode 100644 index 0000000000..c95dfffa13 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/JavaSEFormat.java @@ -0,0 +1,24 @@ +package com.baeldung.localization; + +import java.text.MessageFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class JavaSEFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + final String pattern = bundle.getString("label"); + final MessageFormat formatter = new MessageFormat(pattern, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("Java formatter"); + final Date date = new Date(System.currentTimeMillis()); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 2 }))); + } +} diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/Localization.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/Localization.java new file mode 100644 index 0000000000..17a6598ce0 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/localization/Localization.java @@ -0,0 +1,18 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class Localization { + + public static String getLabel(Locale locale) { + final ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); + return bundle.getString("label"); + } + + public static void run(List locales) { + locales.forEach(locale -> System.out.println(getLabel(locale))); + } + +} diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java new file mode 100644 index 0000000000..65f12ada45 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java @@ -0,0 +1,46 @@ +package com.baeldung.stream; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SkipLimitComparison { + + public static void main(String[] args) { + skipExample(); + limitExample(); + limitInfiniteStreamExample(); + getEvenNumbers(10, 10).stream() + .forEach(System.out::println); + } + + public static void skipExample() { + Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .filter(i -> i % 2 == 0) + .skip(2) + .forEach(i -> System.out.print(i + " ")); + } + + public static void limitExample() { + Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .filter(i -> i % 2 == 0) + .limit(2) + .forEach(i -> System.out.print(i + " ")); + } + + public static void limitInfiniteStreamExample() { + Stream.iterate(0, i -> i + 1) + .filter(i -> i % 2 == 0) + .limit(10) + .forEach(System.out::println); + } + + private static List getEvenNumbers(int offset, int limit) { + return Stream.iterate(0, i -> i + 1) + .filter(i -> i % 2 == 0) + .skip(offset) + .limit(limit) + .collect(Collectors.toList()); + } + +} diff --git a/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml b/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..e8cd723ec2 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,34 @@ + + + + + Persist Optional Return Type Demo + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.optionalReturnType.User + com.baeldung.optionalReturnType.UserOptional + + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt b/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt new file mode 100644 index 0000000000..71abcb05fb --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt @@ -0,0 +1 @@ +Main-Class: com.baeldung.jarArguments.JarExample diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties new file mode 100644 index 0000000000..41e0e00119 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties @@ -0,0 +1,2 @@ +label=On {0, date, short} {1} has sent you {2, choice, 0#no messages|1#a message|2#two messages|2<{2,number,integer} messages}. +label-icu={0} has sent you {2, plural, =0 {no messages} =1 {a message} other {{2, number, integer} messages}}. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties new file mode 100644 index 0000000000..c2d5159b32 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties @@ -0,0 +1,2 @@ +label={0, date, short}, {1}{2, choice, 0# ne|0<} vous a envoy {2, choice, 0#aucun message|1#un message|2#deux messages|2<{2,number,integer} messages}. +label-icu={0} {2, plural, =0 {ne } other {}}vous a envoy {2, plural, =0 {aucun message} =1 {un message} other {{2, number, integer} messages}}. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties new file mode 100644 index 0000000000..43fd1eee1c --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties @@ -0,0 +1,2 @@ +label={0, date, short} {1} ti ha inviato {2, choice, 0#nessun messagio|1#un messaggio|2#due messaggi|2<{2, number, integer} messaggi}. +label-icu={0} {2, plural, =0 {non } other {}}ti ha inviato {2, plural, =0 {nessun messaggio} =1 {un messaggio} other {{2, number, integer} messaggi}}. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties new file mode 100644 index 0000000000..9333ec3396 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties @@ -0,0 +1,2 @@ +label=W {0, date, short} {1}{2, choice, 0# nie|0<} wys\u0142a\u0142a ci {2, choice, 0#\u017Cadnych wiadomo\u015Bci|1#wiadomo\u015B\u0107|2#dwie wiadomo\u015Bci|2<{2, number, integer} wiadomo\u015Bci}. +label-icu={0} {2, plural, =0 {nie } other {}}{1, select, male {wys\u0142a\u0142} female {wys\u0142a\u0142a} other {wys\u0142a\u0142o}} ci {2, plural, =0 {\u017Cadnej wiadomo\u015Bci} =1 {wiadomo\u015B\u0107} other {{2, number, integer} wiadomo\u015Bci}}. diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..bcbca9483c --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties @@ -0,0 +1 @@ +label=Alice has sent you a message. diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..6716102568 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties @@ -0,0 +1 @@ +label=Alice vous a envoy un message. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties new file mode 100644 index 0000000000..6929a8c091 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties @@ -0,0 +1 @@ +label=Alice ti ha inviato un messaggio. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties new file mode 100644 index 0000000000..5515a9920e --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties @@ -0,0 +1 @@ +label=Alice wys\u0142a\u0142a ci wiadomo\u015B\u0107. \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/test/java/com/baeldung/bifunction/BiFunctionalInterfacesUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/bifunction/BiFunctionalInterfacesUnitTest.java new file mode 100644 index 0000000000..ea63409c88 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/bifunction/BiFunctionalInterfacesUnitTest.java @@ -0,0 +1,164 @@ +package com.baeldung.bifunction; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BiFunctionalInterfacesUnitTest { + @Test + public void givenStreamValues_whenMappedToNewValues() { + List mapped = Stream.of("hello", "world") + .map(word -> word + "!") + .collect(Collectors.toList()); + + assertThat(mapped).containsExactly("hello!", "world!"); + } + + @Test + public void givenStreamValues_whenReducedWithPrefixingOperation() { + String result = Stream.of("hello", "world") + .reduce("", (a, b) -> b + "-" + a); + + assertThat(result).isEqualTo("world-hello-"); + } + + @Test + public void givenStreamValues_whenReducedWithPrefixingLambda_thenHasNoTrailingDash() { + String result = Stream.of("hello", "world") + .reduce("", (a, b) -> combineWithoutTrailingDash(a, b)); + + assertThat(result).isEqualTo("world-hello"); + } + + private String combineWithoutTrailingDash(String a, String b) { + if (a.isEmpty()) { + return b; + } + return b + "-" + a; + } + + @Test + public void givenStreamValues_whenReducedWithPrefixingMethodReference_thenHasNoTrailingDash() { + String result = Stream.of("hello", "world") + .reduce("", this::combineWithoutTrailingDash); + + assertThat(result).isEqualTo("world-hello"); + } + + @Test + public void givenTwoLists_whenCombined() { + List list1 = Arrays.asList("a", "b", "c"); + List list2 = Arrays.asList(1, 2, 3); + + List result = new ArrayList<>(); + for (int i=0; i < list1.size(); i++) { + result.add(list1.get(i) + list2.get(i)); + } + + assertThat(result).containsExactly("a1", "b2", "c3"); + } + + @Test + public void givenTwoLists_whenCombinedWithGeneralPurposeCombiner() { + List list1 = Arrays.asList("a", "b", "c"); + List list2 = Arrays.asList(1, 2, 3); + + List result = listCombiner(list1, list2, (a, b) -> a + b); + + assertThat(result).containsExactly("a1", "b2", "c3"); + } + + private static List listCombiner(List list1, + List list2, + BiFunction combiner) { + List result = new ArrayList<>(); + for (int i = 0; i < list1.size(); i++) { + result.add(combiner.apply(list1.get(i), list2.get(i))); + } + return result; + } + + @Test + public void givenTwoLists_whenComparedWithCombiningFunction() { + List list1 = Arrays.asList(1.0d, 2.1d, 3.3d); + List list2 = Arrays.asList(0.1f, 0.2f, 4f); + + // algorithm to determine if the value in list1 > value in list 2 + List result = listCombiner(list1, list2, (a, b) -> a > b); + + assertThat(result).containsExactly(true, true, false); + } + + @Test + public void givenTwoLists_whenComparedWithCombiningFunctionByMethodReference() { + List list1 = Arrays.asList(1.0d, 2.1d, 3.3d); + List list2 = Arrays.asList(0.1f, 0.2f, 4f); + + // algorithm to determine if the value in list1 > value in list 2 + List result = listCombiner(list1, list2, this::firstIsGreaterThanSecond); + + assertThat(result).containsExactly(true, true, false); + } + + private boolean firstIsGreaterThanSecond(Double a, Float b) { + return a > b; + } + + @Test + public void givenTwoLists_whenComparedForEqualityByCombiningFunction() { + List list1 = Arrays.asList(0.1f, 0.2f, 4f); + List list2 = Arrays.asList(0.1f, 0.2f, 4f); + + List result = listCombiner(list1, list2, (a, b) -> a.equals(b)); + + assertThat(result).containsExactly(true, true, true); + } + + @Test + public void givenTwoLists_whenComparedForEqualityByCombiningFunctionWithMethodReference() { + List list1 = Arrays.asList(0.1f, 0.2f, 4f); + List list2 = Arrays.asList(0.1f, 0.2f, 4f); + + List result = listCombiner(list1, list2, Float::equals); + + assertThat(result).containsExactly(true, true, true); + } + + @Test + public void givenTwoLists_whenComparedWithCombiningFunctionWithCompareTo() { + List list1 = Arrays.asList(1.0d, 2.1d, 3.3d); + List list2 = Arrays.asList(0.1d, 0.2d, 4d); + + List result = listCombiner(list1, list2, Double::compareTo); + + assertThat(result).containsExactly(1, 1, -1); + } + + /** + * Allows you to to pass in a lambda or method reference and then + * get access to the BiFunction it is meant to become + */ + private static BiFunction asBiFunction(BiFunction function) { + return function; + } + + @Test + public void givenTwoLists_whenComparedWithCombiningFunctionWithComposedBiFunction() { + List list1 = Arrays.asList(1.0d, 2.1d, 3.3d); + List list2 = Arrays.asList(0.1d, 0.2d, 4d); + + List result = listCombiner(list1, list2, + asBiFunction(Double::compareTo) + .andThen(i -> i > 0)); + + assertThat(result).containsExactly(true, true, false); + } +} diff --git a/core-java-modules/core-java-8-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java new file mode 100644 index 0000000000..2c8f9b47f3 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.localization; + +import static org.junit.Assert.assertEquals; + +import java.util.Locale; + +import org.junit.Test; + +import com.baeldung.localization.ICUFormat; + +public class ICUFormatUnitTest { + + @Test + public void givenInUK_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice has sent you no messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInUK_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice has sent you a message.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInUK_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob has sent you 6 messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInItaly_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice non ti ha inviato nessun messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInItaly_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice ti ha inviato un messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInItaly_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob ti ha inviato 6 messaggi.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInFrance_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice ne vous a envoyé aucun message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInFrance_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice vous a envoyé un message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInFrance_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob vous a envoyé 6 messages.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Bob", "male", 6 })); + } + + + @Test + public void givenInPoland_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice nie wysłała ci żadnej wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInPoland_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice wysłała ci wiadomość.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInPoland_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob wysłał ci 6 wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Bob", "male", 6 })); + } + +} diff --git a/core-java-8/.gitignore b/core-java-modules/core-java-8/.gitignore similarity index 100% rename from core-java-8/.gitignore rename to core-java-modules/core-java-8/.gitignore diff --git a/core-java-8/README.md b/core-java-modules/core-java-8/README.md similarity index 73% rename from core-java-8/README.md rename to core-java-modules/core-java-8/README.md index 6786b29120..b2ae48ea11 100644 --- a/core-java-8/README.md +++ b/core-java-modules/core-java-8/README.md @@ -3,10 +3,10 @@ ## Core Java 8 Cookbooks and Examples ### 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) +- [Guide to Java 8’s 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) @@ -15,7 +15,6 @@ - [Guide to Java 8 Comparator.comparing()](http://www.baeldung.com/java-8-comparator-comparing) - [Guide To Java 8 Optional](http://www.baeldung.com/java-optional) - [Guide to the Java 8 forEach](http://www.baeldung.com/foreach-java) -- [Java Base64 Encoding and Decoding](http://www.baeldung.com/java-base64-encode-and-decode) - [The Difference Between map() and flatMap()](http://www.baeldung.com/java-difference-map-and-flatmap) - [Static and Default Methods in Interfaces in Java](http://www.baeldung.com/java-static-default-methods) - [Efficient Word Frequency Calculator in Java](http://www.baeldung.com/java-word-frequency) @@ -34,3 +33,11 @@ - [Java Primitives versus Objects](https://www.baeldung.com/java-primitives-vs-objects) - [How to Use if/else Logic in Java 8 Streams](https://www.baeldung.com/java-8-streams-if-else-logic) - [How to Replace Many if Statements in Java](https://www.baeldung.com/java-replace-if-statements) +- [Java @Override Annotation](https://www.baeldung.com/java-override) +- [Java @SuppressWarnings Annotation](https://www.baeldung.com/java-suppresswarnings) +- [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) +- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation) +- [The Difference Between Collection.stream().forEach() and Collection.forEach()](https://www.baeldung.com/java-collection-stream-foreach) diff --git a/core-java-8/pom.xml b/core-java-modules/core-java-8/pom.xml similarity index 78% rename from core-java-8/pom.xml rename to core-java-modules/core-java-8/pom.xml index 18bdaa15f4..c09c970e07 100644 --- a/core-java-8/pom.xml +++ b/core-java-modules/core-java-8/pom.xml @@ -1,167 +1,199 @@ - - 4.0.0 - com.baeldung - core-java-8 - 0.1.0-SNAPSHOT - jar - core-java-8 - - - 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} - - - org.apache.commons - commons-math3 - ${commons-math3.version} - - - log4j - log4j - ${log4j.version} - - - commons-codec - commons-codec - ${commons-codec.version} - - - org.projectlombok - lombok - ${lombok.version} - provided - - - - org.assertj - assertj-core - ${assertj.version} - test - - - com.jayway.awaitility - awaitility - ${avaitility.version} - test - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-generator.version} - - - org.openjdk.jmh - jmh-generator-bytecode - ${jmh-generator.version} - - - com.codepoetics - protonpack - ${protonpack.version} - - - io.vavr - vavr - ${vavr.version} - - - joda-time - joda-time - ${joda.version} - - - org.aspectj - aspectjrt - ${asspectj.version} - - - org.aspectj - aspectjweaver - ${asspectj.version} - - - - - core-java-8 - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - -parameters - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-maven-plugin.version} - - - - repackage - - - spring-boot - org.baeldung.executable.ExecutableMavenJar - - - - - - - - - - 3.5 - 3.6.1 - 4.1 - 4.01 - 1.10 - 1.16.12 - 0.9.0 - 1.13 - 2.10 - - 3.6.1 - 1.8.9 - 1.7.0 - 1.19 - 1.19 - 2.0.4.RELEASE - - + + 4.0.0 + com.baeldung + core-java-8 + 0.1.0-SNAPSHOT + core-java-8 + 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} + + + org.apache.commons + commons-math3 + ${commons-math3.version} + + + log4j + log4j + ${log4j.version} + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + org.assertj + assertj-core + ${assertj.version} + test + + + com.jayway.awaitility + awaitility + ${avaitility.version} + test + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator.version} + + + org.openjdk.jmh + jmh-generator-bytecode + ${jmh-generator.version} + + + com.codepoetics + protonpack + ${protonpack.version} + + + io.vavr + vavr + ${vavr.version} + + + joda-time + joda-time + ${joda.version} + + + org.aspectj + aspectjrt + ${asspectj.version} + + + org.aspectj + aspectjweaver + ${asspectj.version} + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + + + org.jmockit + jmockit + ${jmockit.version} + test + + + + + core-java-8 + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + -parameters + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-maven-plugin.version} + + + + repackage + + + spring-boot + org.baeldung.executable.ExecutableMavenJar + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + -javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar + + true + + + + + + + + 3.5 + 3.6.1 + 4.1 + 4.01 + 1.10 + 0.9.0 + 1.13 + 2.10 + + 3.6.1 + 1.8.9 + 2.0.0-RC.4 + 1.44 + 1.7.0 + 1.19 + 1.19 + 2.0.4.RELEASE + + 3.8.0 + 2.22.1 + + diff --git a/core-java-8/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithAnnotation.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithDeprecatedMethod.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSafeVarargs.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/ClassWithSuppressWarnings.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/IntConsumer.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/IntConsumer.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/IntConsumer.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/IntConsumer.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/Interval.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/Interval.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/Interval.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/Interval.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/IntervalUsage.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/IntervalUsage.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/IntervalUsage.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/IntervalUsage.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/Intervals.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/Intervals.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/Intervals.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/Intervals.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotation.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotation.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/MyAnnotation.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotation.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyAnnotationTarget.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/MyOperation.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyOperation.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/MyOperation.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyOperation.java diff --git a/core-java-8/src/main/java/com/baeldung/annotations/MyOperationImpl.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyOperationImpl.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/annotations/MyOperationImpl.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/annotations/MyOperationImpl.java diff --git a/core-java-8/src/main/java/com/baeldung/aspect/ChangeCallsToCurrentTimeInMillisMethod.aj b/core-java-modules/core-java-8/src/main/java/com/baeldung/aspect/ChangeCallsToCurrentTimeInMillisMethod.aj similarity index 100% rename from core-java-8/src/main/java/com/baeldung/aspect/ChangeCallsToCurrentTimeInMillisMethod.aj rename to core-java-modules/core-java-8/src/main/java/com/baeldung/aspect/ChangeCallsToCurrentTimeInMillisMethod.aj diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Init.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Init.java new file mode 100644 index 0000000000..c27d7d7980 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Init.java @@ -0,0 +1,13 @@ +package com.baeldung.customannotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(METHOD) +public @interface Init { + +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java new file mode 100644 index 0000000000..3c953f9081 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java @@ -0,0 +1,13 @@ +package com.baeldung.customannotations; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target({ FIELD }) +public @interface JsonElement { + public String key() default ""; +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java new file mode 100644 index 0000000000..f6feba1b7b --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java @@ -0,0 +1,13 @@ +package com.baeldung.customannotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(TYPE) +public @interface JsonSerializable { + +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java new file mode 100644 index 0000000000..544d1311aa --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java @@ -0,0 +1,10 @@ +package com.baeldung.customannotations; + +public class JsonSerializationException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public JsonSerializationException(String message) { + super(message); + } +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java new file mode 100644 index 0000000000..b809ea0d1d --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java @@ -0,0 +1,67 @@ +package com.baeldung.customannotations; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class ObjectToJsonConverter { + public String convertToJson(Object object) throws JsonSerializationException { + try { + + checkIfSerializable(object); + initializeObject(object); + return getJsonString(object); + + } catch (Exception e) { + throw new JsonSerializationException(e.getMessage()); + } + } + + private void checkIfSerializable(Object object) { + if (Objects.isNull(object)) { + throw new JsonSerializationException("Can't serialize a null object"); + } + + Class clazz = object.getClass(); + if (!clazz.isAnnotationPresent(JsonSerializable.class)) { + throw new JsonSerializationException("The class " + clazz.getSimpleName() + " is not annotated with JsonSerializable"); + } + } + + private void initializeObject(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Class clazz = object.getClass(); + for (Method method : clazz.getDeclaredMethods()) { + if (method.isAnnotationPresent(Init.class)) { + method.setAccessible(true); + method.invoke(object); + } + } + } + + private String getJsonString(Object object) throws IllegalArgumentException, IllegalAccessException { + Class clazz = object.getClass(); + Map jsonElementsMap = new HashMap<>(); + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + if (field.isAnnotationPresent(JsonElement.class)) { + jsonElementsMap.put(getKey(field), (String) field.get(object)); + } + } + + String jsonString = jsonElementsMap.entrySet() + .stream() + .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"") + .collect(Collectors.joining(",")); + return "{" + jsonString + "}"; + } + + private String getKey(Field field) { + String value = field.getAnnotation(JsonElement.class) + .key(); + return value.isEmpty() ? field.getName() : value; + } +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Person.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Person.java new file mode 100644 index 0000000000..ba702d6d76 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/customannotations/Person.java @@ -0,0 +1,66 @@ +package com.baeldung.customannotations; + +@JsonSerializable +public class Person { + @JsonElement + private String firstName; + @JsonElement + private String lastName; + @JsonElement(key = "personAge") + private String age; + + private String address; + + public Person(String firstName, String lastName) { + super(); + this.firstName = firstName; + this.lastName = lastName; + } + + public Person(String firstName, String lastName, String age) { + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + @Init + private void initNames() { + this.firstName = this.firstName.substring(0, 1) + .toUpperCase() + this.firstName.substring(1); + this.lastName = this.lastName.substring(0, 1) + .toUpperCase() + this.lastName.substring(1); + } + + 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 getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/application/Application.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/application/Application.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/application/Application.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/application/Application.java diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Alarm.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Alarm.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Alarm.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Alarm.java diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Car.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Car.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Car.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Car.java diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Motorbike.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Motorbike.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Motorbike.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Motorbike.java diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/MultiAlarmCar.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/MultiAlarmCar.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/MultiAlarmCar.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/MultiAlarmCar.java diff --git a/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Vehicle.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Vehicle.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Vehicle.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/defaultstaticinterfacemethods/model/Vehicle.java diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java diff --git a/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java diff --git a/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java diff --git a/core-java-8/src/main/java/com/baeldung/Bar.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java similarity index 80% rename from core-java-8/src/main/java/com/baeldung/Bar.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java index 6219bddf74..4cf0aa2399 100644 --- a/core-java-8/src/main/java/com/baeldung/Bar.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.java8.lambda.tips; @FunctionalInterface diff --git a/core-java-8/src/main/java/com/baeldung/Baz.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java similarity index 80% rename from core-java-8/src/main/java/com/baeldung/Baz.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java index 23180551ac..c7efe14c89 100644 --- a/core-java-8/src/main/java/com/baeldung/Baz.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.java8.lambda.tips; @FunctionalInterface diff --git a/core-java-8/src/main/java/com/baeldung/Foo.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java similarity index 75% rename from core-java-8/src/main/java/com/baeldung/Foo.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java index c8223727a1..b63ba61e7e 100644 --- a/core-java-8/src/main/java/com/baeldung/Foo.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.java8.lambda.tips; @FunctionalInterface diff --git a/core-java-8/src/main/java/com/baeldung/FooExtended.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java similarity index 81% rename from core-java-8/src/main/java/com/baeldung/FooExtended.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java index 8c9b21e397..9141cd8eb8 100644 --- a/core-java-8/src/main/java/com/baeldung/FooExtended.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.java8.lambda.tips; @FunctionalInterface diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java new file mode 100644 index 0000000000..7931129cf5 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java @@ -0,0 +1,12 @@ +package com.baeldung.java8.lambda.tips; + +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +public interface Processor { + + String processWithCallable(Callable c) throws Exception; + + String processWithSupplier(Supplier s); + +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java new file mode 100644 index 0000000000..cb1b3dcdd2 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java @@ -0,0 +1,20 @@ +package com.baeldung.java8.lambda.tips; + + +import java.util.concurrent.Callable; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class ProcessorImpl implements Processor { + + @Override + public String processWithCallable(Callable c) throws Exception { + return c.call(); + } + + @Override + public String processWithSupplier(Supplier s) { + return s.get(); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/UseFoo.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java similarity index 95% rename from core-java-8/src/main/java/com/baeldung/UseFoo.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java index 950d02062d..a64d8bb920 100644 --- a/core-java-8/src/main/java/com/baeldung/UseFoo.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.java8.lambda.tips; import java.util.function.Function; diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/Address.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/User.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/User.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/User.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/User.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java diff --git a/core-java-8/src/main/java/com/baeldung/optional/Modem.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/optional/Modem.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/optional/Modem.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/optional/Modem.java diff --git a/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGet.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGet.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGet.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGet.java diff --git a/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGetBenchmarkRunner.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGetBenchmarkRunner.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGetBenchmarkRunner.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/optional/OrElseAndOrElseGetBenchmarkRunner.java diff --git a/core-java-8/src/main/java/com/baeldung/optional/Person.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/optional/Person.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/optional/Person.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/optional/Person.java diff --git a/core-java-8/src/main/java/com/baeldung/optional/PersonRepository.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/optional/PersonRepository.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/optional/PersonRepository.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/optional/PersonRepository.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/BenchmarkRunner.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BenchmarkRunner.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/BenchmarkRunner.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BenchmarkRunner.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/BooleanPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BooleanPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/BooleanPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BooleanPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/BooleanWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BooleanWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/BooleanWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BooleanWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/BytePrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BytePrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/BytePrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/BytePrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/ByteWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ByteWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/ByteWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ByteWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/CharPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/CharPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/CharPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/CharPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/CharacterWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/CharacterWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/CharacterWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/CharacterWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/DoublePrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/DoublePrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/DoublePrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/DoublePrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/DoubleWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/DoubleWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/DoubleWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/DoubleWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/FloatPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/FloatPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/FloatPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/FloatPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/FloatWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/FloatWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/FloatWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/FloatWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/IntPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/IntPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/IntPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/IntPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/IntegerWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/IntegerWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/IntegerWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/IntegerWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/LongPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/LongPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/LongPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/LongPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/LongWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/LongWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/LongWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/LongWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/Lookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/Lookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/Lookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/Lookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/ShortPrimitiveLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ShortPrimitiveLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/ShortPrimitiveLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ShortPrimitiveLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/primitive/ShortWrapperLookup.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ShortWrapperLookup.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/primitive/ShortWrapperLookup.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/primitive/ShortWrapperLookup.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddCommand.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddCommand.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/AddCommand.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddCommand.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddRule.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddRule.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/AddRule.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/AddRule.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Addition.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Addition.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Addition.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Addition.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Calculator.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Calculator.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Calculator.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Calculator.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Command.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Command.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Command.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Command.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Division.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Division.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Division.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Division.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Expression.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Expression.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Expression.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Expression.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Modulo.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Modulo.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Modulo.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Modulo.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Multiplication.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Multiplication.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Multiplication.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Multiplication.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operation.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operation.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Operation.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operation.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operator.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operator.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Operator.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Operator.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/OperatorFactory.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/OperatorFactory.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/OperatorFactory.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/OperatorFactory.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Result.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Result.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Result.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Result.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Rule.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Rule.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Rule.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Rule.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/RuleEngine.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/RuleEngine.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/RuleEngine.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/RuleEngine.java diff --git a/core-java-8/src/main/java/com/baeldung/reducingIfElse/Subtraction.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Subtraction.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/reducingIfElse/Subtraction.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reducingIfElse/Subtraction.java diff --git a/core-java-8/src/main/java/com/baeldung/reflect/Person.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/reflect/Person.java similarity index 93% rename from core-java-8/src/main/java/com/baeldung/reflect/Person.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/reflect/Person.java index fba25aca8b..f15250869d 100644 --- a/core-java-8/src/main/java/com/baeldung/reflect/Person.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/reflect/Person.java @@ -1,18 +1,18 @@ -package com.baeldung.reflect; - -public class Person { - - private String fullName; - - public Person(String fullName) { - this.fullName = fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public String getFullName() { - return fullName; - } -} +package com.baeldung.reflect; + +public class Person { + + private String fullName; + + public Person(String fullName) { + this.fullName = fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getFullName() { + return fullName; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java similarity index 94% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java index 402ec6ec5f..3cd2a00da1 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java @@ -1,44 +1,44 @@ -package com.baeldung.spliteratorAPI; - -import java.util.List; - -public class Article { - private List listOfAuthors; - private int id; - private String name; - - public Article(String name) { - this.name = name; - } - - public Article(List listOfAuthors, int id) { - super(); - this.listOfAuthors = listOfAuthors; - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public List getListOfAuthors() { - return listOfAuthors; - } - - public void setListOfAuthors(List listOfAuthors) { - this.listOfAuthors = listOfAuthors; - } - +package com.baeldung.spliteratorAPI; + +import java.util.List; + +public class Article { + private List listOfAuthors; + private int id; + private String name; + + public Article(String name) { + this.name = name; + } + + public Article(List listOfAuthors, int id) { + super(); + this.listOfAuthors = listOfAuthors; + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getListOfAuthors() { + return listOfAuthors; + } + + public void setListOfAuthors(List listOfAuthors) { + this.listOfAuthors = listOfAuthors; + } + } \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java similarity index 95% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java index 40c381f4a6..18bbbd073e 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java @@ -1,33 +1,33 @@ -package com.baeldung.spliteratorAPI; - -public class Author { - private String name; - private int relatedArticleId; - - public Author(String name, int relatedArticleId) { - this.name = name; - this.relatedArticleId = relatedArticleId; - } - - public int getRelatedArticleId() { - return relatedArticleId; - } - - public void setRelatedArticleId(int relatedArticleId) { - this.relatedArticleId = relatedArticleId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return "[name: " + name + ", relatedId: " + relatedArticleId + "]"; - } -} - +package com.baeldung.spliteratorAPI; + +public class Author { + private String name; + private int relatedArticleId; + + public Author(String name, int relatedArticleId) { + this.name = name; + this.relatedArticleId = relatedArticleId; + } + + public int getRelatedArticleId() { + return relatedArticleId; + } + + public void setRelatedArticleId(int relatedArticleId) { + this.relatedArticleId = relatedArticleId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "[name: " + name + ", relatedId: " + relatedArticleId + "]"; + } +} + diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java similarity index 96% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java index 024d5dabdb..dd124948d8 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java @@ -1,19 +1,19 @@ -package com.baeldung.spliteratorAPI; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class Executor { - - public static int countAutors(Stream stream) { - RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true), - RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine); - return wordCounter.getCounter(); - } - - public static List
generateElements() { - return Stream.generate(() -> new Article("Java")).limit(35000).collect(Collectors.toList()); - } - +package com.baeldung.spliteratorAPI; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Executor { + + public static int countAutors(Stream stream) { + RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true), + RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine); + return wordCounter.getCounter(); + } + + public static List
generateElements() { + return Stream.generate(() -> new Article("Java")).limit(35000).collect(Collectors.toList()); + } + } \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java similarity index 96% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java index b7120b3af2..282c0be727 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java @@ -1,27 +1,27 @@ -package com.baeldung.spliteratorAPI; - -public class RelatedAuthorCounter { - private final int counter; - private final boolean isRelated; - - public RelatedAuthorCounter(int counter, boolean isRelated) { - this.counter = counter; - this.isRelated = isRelated; - } - - public RelatedAuthorCounter accumulate(Author author) { - if (author.getRelatedArticleId() == 0) { - return isRelated ? this : new RelatedAuthorCounter(counter, true); - } else { - return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this; - } - } - - public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) { - return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated); - } - - public int getCounter() { - return counter; - } -} +package com.baeldung.spliteratorAPI; + +public class RelatedAuthorCounter { + private final int counter; + private final boolean isRelated; + + public RelatedAuthorCounter(int counter, boolean isRelated) { + this.counter = counter; + this.isRelated = isRelated; + } + + public RelatedAuthorCounter accumulate(Author author) { + if (author.getRelatedArticleId() == 0) { + return isRelated ? this : new RelatedAuthorCounter(counter, true); + } else { + return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this; + } + } + + public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) { + return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated); + } + + public int getCounter() { + return counter; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java similarity index 96% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java index 0a7190964e..094638da37 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java @@ -1,49 +1,49 @@ -package com.baeldung.spliteratorAPI; - -import java.util.List; -import java.util.Spliterator; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -public class RelatedAuthorSpliterator implements Spliterator { - private final List list; - AtomicInteger current = new AtomicInteger(); - - public RelatedAuthorSpliterator(List list) { - this.list = list; - } - - @Override - public boolean tryAdvance(Consumer action) { - - action.accept(list.get(current.getAndIncrement())); - return current.get() < list.size(); - } - - @Override - public Spliterator trySplit() { - int currentSize = list.size() - current.get(); - if (currentSize < 10) { - return null; - } - for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) { - if (list.get(splitPos).getRelatedArticleId() == 0) { - Spliterator spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos)); - current.set(splitPos); - return spliterator; - } - } - return null; - } - - @Override - public long estimateSize() { - return list.size() - current.get(); - } - - @Override - public int characteristics() { - return CONCURRENT; - } - -} +package com.baeldung.spliteratorAPI; + +import java.util.List; +import java.util.Spliterator; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +public class RelatedAuthorSpliterator implements Spliterator { + private final List list; + AtomicInteger current = new AtomicInteger(); + + public RelatedAuthorSpliterator(List list) { + this.list = list; + } + + @Override + public boolean tryAdvance(Consumer action) { + + action.accept(list.get(current.getAndIncrement())); + return current.get() < list.size(); + } + + @Override + public Spliterator trySplit() { + int currentSize = list.size() - current.get(); + if (currentSize < 10) { + return null; + } + for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) { + if (list.get(splitPos).getRelatedArticleId() == 0) { + Spliterator spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos)); + current.set(splitPos); + return spliterator; + } + } + return null; + } + + @Override + public long estimateSize() { + return list.size() - current.get(); + } + + @Override + public int characteristics() { + return CONCURRENT; + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java similarity index 96% rename from core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java index 70435d1c75..06a124cc98 100644 --- a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java @@ -1,27 +1,27 @@ -package com.baeldung.spliteratorAPI; - -import java.util.Spliterator; -import java.util.concurrent.Callable; - -public class Task implements Callable { - private Spliterator
spliterator; - private final static String SUFFIX = "- published by Baeldung"; - - public Task(Spliterator
spliterator) { - this.spliterator = spliterator; - } - - @Override - public String call() { - int current = 0; - while (spliterator.tryAdvance(article -> { - article.setName(article.getName() - .concat(SUFFIX)); - })) { - current++; - } - ; - return Thread.currentThread() - .getName() + ":" + current; - } -} +package com.baeldung.spliteratorAPI; + +import java.util.Spliterator; +import java.util.concurrent.Callable; + +public class Task implements Callable { + private Spliterator
spliterator; + private final static String SUFFIX = "- published by Baeldung"; + + public Task(Spliterator
spliterator) { + this.spliterator = spliterator; + } + + @Override + public String call() { + int current = 0; + while (spliterator.tryAdvance(article -> { + article.setName(article.getName() + .concat(SUFFIX)); + })) { + current++; + } + ; + return Thread.currentThread() + .getName() + ":" + current; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java diff --git a/core-java-8/src/main/java/com/baeldung/strategy/Discounter.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/Discounter.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/strategy/Discounter.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/Discounter.java diff --git a/core-java-8/src/main/java/com/baeldung/strategy/EasterDiscounter.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/EasterDiscounter.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/strategy/EasterDiscounter.java rename to core-java-modules/core-java-8/src/main/java/com/baeldung/strategy/EasterDiscounter.java diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java new file mode 100644 index 0000000000..00fc45ccae --- /dev/null +++ b/core-java-modules/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-modules/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java new file mode 100644 index 0000000000..39a42beab7 --- /dev/null +++ b/core-java-modules/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-modules/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..a2325cc701 --- /dev/null +++ b/core-java-modules/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-collections/src/main/resources/logback.xml b/core-java-modules/core-java-8/src/main/resources/logback.xml similarity index 100% rename from core-java-collections/src/main/resources/logback.xml rename to core-java-modules/core-java-8/src/main/resources/logback.xml diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java similarity index 86% rename from core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java index bad1c32e4a..e742635758 100644 --- a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java @@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; public class Java8CollectorsUnitTest { private final List givenList = Arrays.asList("a", "bb", "ccc", "dd"); + private final List listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb"); @Test public void whenCollectingToList_shouldCollectToList() throws Exception { @@ -48,12 +49,19 @@ public class Java8CollectorsUnitTest { } @Test - public void whenCollectingToList_shouldCollectToSet() throws Exception { + public void whenCollectingToSet_shouldCollectToSet() throws Exception { final Set result = givenList.stream().collect(toSet()); assertThat(result).containsAll(givenList); } + @Test + public void givenContainsDuplicateElements_whenCollectingToSet_shouldAddDuplicateElementsOnlyOnce() throws Exception { + final Set result = listWithDuplicates.stream().collect(toSet()); + + assertThat(result).hasSize(4); + } + @Test public void whenCollectingToCollection_shouldCollectToCollection() throws Exception { final List result = givenList.stream().collect(toCollection(LinkedList::new)); @@ -77,10 +85,23 @@ public class Java8CollectorsUnitTest { } @Test - public void whenCollectingToMap_shouldCollectToMapMerging() throws Exception { - final Map result = givenList.stream().collect(toMap(Function.identity(), String::length, (i1, i2) -> i1)); + public void whenCollectingToMapwWithDuplicates_shouldCollectToMapMergingTheIdenticalItems() throws Exception { + final Map result = listWithDuplicates.stream().collect( + toMap( + Function.identity(), + String::length, + (item, identicalItem) -> item + ) + ); - assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("ccc", 3).containsEntry("dd", 2); + assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("c", 1).containsEntry("d", 1); + } + + @Test + public void givenContainsDuplicateElements_whenCollectingToMap_shouldThrowException() throws Exception { + assertThatThrownBy(() -> { + listWithDuplicates.stream().collect(toMap(Function.identity(), String::length)); + }).isInstanceOf(IllegalStateException.class); } @Test diff --git a/core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java similarity index 97% rename from core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java index 015ca3f942..e5b03bf355 100644 --- a/core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterStatistics.java @@ -1,61 +1,61 @@ -package com.baeldung.counter; - -import java.util.HashMap; -import java.util.Map; -import java.util.Random; - -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 com.baeldung.counter.CounterUtil.MutableInteger; - -@Fork(value = 1, warmups = 3) -@BenchmarkMode(Mode.All) -public class CounterStatistics { - - private static final Map counterMap = new HashMap<>(); - private static final Map counterWithMutableIntMap = new HashMap<>(); - private static final Map counterWithIntArrayMap = new HashMap<>(); - private static final Map counterWithLongWrapperMap = new HashMap<>(); - private static final Map counterWithLongWrapperStreamMap = new HashMap<>(); - - static { - CounterUtil.COUNTRY_NAMES = new String[10000]; - final String prefix = "NewString"; - Random random = new Random(); - for (int i=0; i<10000; i++) { - CounterUtil.COUNTRY_NAMES[i] = new String(prefix + random.nextInt(1000)); - } - } - - @Benchmark - public void wrapperAsCounter() { - CounterUtil.counterWithWrapperObject(counterMap); - } - - @Benchmark - public void lambdaExpressionWithWrapper() { - CounterUtil.counterWithLambdaAndWrapper(counterWithLongWrapperMap); - } - - @Benchmark - public void parallelStreamWithWrapper() { - CounterUtil.counterWithParallelStreamAndWrapper(counterWithLongWrapperStreamMap); - } - - @Benchmark - public void mutableIntegerAsCounter() { - CounterUtil.counterWithMutableInteger(counterWithMutableIntMap); - } - - @Benchmark - public void primitiveArrayAsCounter() { - CounterUtil.counterWithPrimitiveArray(counterWithIntArrayMap); - } - - public static void main(String[] args) throws Exception { - org.openjdk.jmh.Main.main(args); - } -} +package com.baeldung.counter; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +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 com.baeldung.counter.CounterUtil.MutableInteger; + +@Fork(value = 1, warmups = 3) +@BenchmarkMode(Mode.All) +public class CounterStatistics { + + private static final Map counterMap = new HashMap<>(); + private static final Map counterWithMutableIntMap = new HashMap<>(); + private static final Map counterWithIntArrayMap = new HashMap<>(); + private static final Map counterWithLongWrapperMap = new HashMap<>(); + private static final Map counterWithLongWrapperStreamMap = new HashMap<>(); + + static { + CounterUtil.COUNTRY_NAMES = new String[10000]; + final String prefix = "NewString"; + Random random = new Random(); + for (int i=0; i<10000; i++) { + CounterUtil.COUNTRY_NAMES[i] = new String(prefix + random.nextInt(1000)); + } + } + + @Benchmark + public void wrapperAsCounter() { + CounterUtil.counterWithWrapperObject(counterMap); + } + + @Benchmark + public void lambdaExpressionWithWrapper() { + CounterUtil.counterWithLambdaAndWrapper(counterWithLongWrapperMap); + } + + @Benchmark + public void parallelStreamWithWrapper() { + CounterUtil.counterWithParallelStreamAndWrapper(counterWithLongWrapperStreamMap); + } + + @Benchmark + public void mutableIntegerAsCounter() { + CounterUtil.counterWithMutableInteger(counterWithMutableIntMap); + } + + @Benchmark + public void primitiveArrayAsCounter() { + CounterUtil.counterWithPrimitiveArray(counterWithIntArrayMap); + } + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java similarity index 96% rename from core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java index ef57fc2c6e..4f914bd289 100644 --- a/core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUnitTest.java @@ -1,53 +1,53 @@ -package com.baeldung.counter; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import com.baeldung.counter.CounterUtil.MutableInteger; - -public class CounterUnitTest { - - @Test - public void whenMapWithWrapperAsCounter_runsSuccessfully() { - Map counterMap = new HashMap<>(); - CounterUtil.counterWithWrapperObject(counterMap); - - assertEquals(3, counterMap.get("China") - .intValue()); - assertEquals(2, counterMap.get("India") - .intValue()); - } - - @Test - public void whenMapWithLambdaAndWrapperCounter_runsSuccessfully() { - Map counterMap = new HashMap<>(); - CounterUtil.counterWithLambdaAndWrapper(counterMap); - - assertEquals(3l, counterMap.get("China") - .longValue()); - assertEquals(2l, counterMap.get("India") - .longValue()); - } - - @Test - public void whenMapWithMutableIntegerCounter_runsSuccessfully() { - Map counterMap = new HashMap<>(); - CounterUtil.counterWithMutableInteger(counterMap); - assertEquals(3, counterMap.get("China") - .getCount()); - assertEquals(2, counterMap.get("India") - .getCount()); - } - - @Test - public void whenMapWithPrimitiveArray_runsSuccessfully() { - Map counterMap = new HashMap<>(); - CounterUtil.counterWithPrimitiveArray(counterMap); - assertEquals(3, counterMap.get("China")[0]); - assertEquals(2, counterMap.get("India")[0]); - } -} +package com.baeldung.counter; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.baeldung.counter.CounterUtil.MutableInteger; + +public class CounterUnitTest { + + @Test + public void whenMapWithWrapperAsCounter_runsSuccessfully() { + Map counterMap = new HashMap<>(); + CounterUtil.counterWithWrapperObject(counterMap); + + assertEquals(3, counterMap.get("China") + .intValue()); + assertEquals(2, counterMap.get("India") + .intValue()); + } + + @Test + public void whenMapWithLambdaAndWrapperCounter_runsSuccessfully() { + Map counterMap = new HashMap<>(); + CounterUtil.counterWithLambdaAndWrapper(counterMap); + + assertEquals(3l, counterMap.get("China") + .longValue()); + assertEquals(2l, counterMap.get("India") + .longValue()); + } + + @Test + public void whenMapWithMutableIntegerCounter_runsSuccessfully() { + Map counterMap = new HashMap<>(); + CounterUtil.counterWithMutableInteger(counterMap); + assertEquals(3, counterMap.get("China") + .getCount()); + assertEquals(2, counterMap.get("India") + .getCount()); + } + + @Test + public void whenMapWithPrimitiveArray_runsSuccessfully() { + Map counterMap = new HashMap<>(); + CounterUtil.counterWithPrimitiveArray(counterMap); + assertEquals(3, counterMap.get("China")[0]); + assertEquals(2, counterMap.get("India")[0]); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java similarity index 96% rename from core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java index c2bf47e213..7e15fa1356 100644 --- a/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/counter/CounterUtil.java @@ -1,57 +1,57 @@ -package com.baeldung.counter; - -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class CounterUtil { - - public static String[] COUNTRY_NAMES = { "China", "Australia", "India", "USA", "USSR", "UK", "China", "France", "Poland", "Austria", "India", "USA", "Egypt", "China" }; - - public static void counterWithWrapperObject(Map counterMap) { - for (String country : COUNTRY_NAMES) { - counterMap.compute(country, (k, v) -> v == null ? 1 : v + 1); - } - } - - public static void counterWithLambdaAndWrapper(Map counterMap) { - Stream.of(COUNTRY_NAMES) - .collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting())); - } - - public static void counterWithParallelStreamAndWrapper(Map counterMap) { - Stream.of(COUNTRY_NAMES) - .parallel() - .collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting())); - } - - public static class MutableInteger { - int count; - - public MutableInteger(int count) { - this.count = count; - } - - public void increment() { - this.count++; - } - - public int getCount() { - return this.count; - } - } - - public static void counterWithMutableInteger(Map counterMap) { - for (String country : COUNTRY_NAMES) { - counterMap.compute(country, (k, v) -> v == null ? new MutableInteger(0) : v) - .increment(); - } - } - - public static void counterWithPrimitiveArray(Map counterMap) { - for (String country : COUNTRY_NAMES) { - counterMap.compute(country, (k, v) -> v == null ? new int[] { 0 } : v)[0]++; - } - } - +package com.baeldung.counter; + +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class CounterUtil { + + public static String[] COUNTRY_NAMES = { "China", "Australia", "India", "USA", "USSR", "UK", "China", "France", "Poland", "Austria", "India", "USA", "Egypt", "China" }; + + public static void counterWithWrapperObject(Map counterMap) { + for (String country : COUNTRY_NAMES) { + counterMap.compute(country, (k, v) -> v == null ? 1 : v + 1); + } + } + + public static void counterWithLambdaAndWrapper(Map counterMap) { + Stream.of(COUNTRY_NAMES) + .collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting())); + } + + public static void counterWithParallelStreamAndWrapper(Map counterMap) { + Stream.of(COUNTRY_NAMES) + .parallel() + .collect(Collectors.groupingBy(k -> k, () -> counterMap, Collectors.counting())); + } + + public static class MutableInteger { + int count; + + public MutableInteger(int count) { + this.count = count; + } + + public void increment() { + this.count++; + } + + public int getCount() { + return this.count; + } + } + + public static void counterWithMutableInteger(Map counterMap) { + for (String country : COUNTRY_NAMES) { + counterMap.compute(country, (k, v) -> v == null ? new MutableInteger(0) : v) + .increment(); + } + } + + public static void counterWithPrimitiveArray(Map counterMap) { + for (String country : COUNTRY_NAMES) { + counterMap.compute(country, (k, v) -> v == null ? new int[] { 0 } : v)[0]++; + } + } + } \ No newline at end of file diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java new file mode 100644 index 0000000000..fd8f8ba8b3 --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.customannotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class JsonSerializerUnitTest { + + @Test + public void givenObjectNotSerializedThenExceptionThrown() throws JsonSerializationException { + Object object = new Object(); + ObjectToJsonConverter serializer = new ObjectToJsonConverter(); + assertThrows(JsonSerializationException.class, () -> { + serializer.convertToJson(object); + }); + } + + @Test + public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException { + Person person = new Person("soufiane", "cheouati", "34"); + ObjectToJsonConverter serializer = new ObjectToJsonConverter(); + String jsonString = serializer.convertToJson(person); + assertEquals("{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/defaultistaticinterfacemethods/test/StaticDefaulInterfaceMethodUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/defaultistaticinterfacemethods/test/StaticDefaulInterfaceMethodUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/defaultistaticinterfacemethods/test/StaticDefaulInterfaceMethodUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/defaultistaticinterfacemethods/test/StaticDefaulInterfaceMethodUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java diff --git a/core-java-8/src/test/java/com/baeldung/internationalization/DateFormatUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/internationalization/DateFormatUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/internationalization/DateFormatUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/internationalization/DateFormatUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/internationalization/NumbersCurrenciesFormattingUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/internationalization/NumbersCurrenciesFormattingUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/internationalization/NumbersCurrenciesFormattingUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/internationalization/NumbersCurrenciesFormattingUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8ForEachUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8ForEachUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8ForEachUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8ForEachUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8OptionalUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalUnitTest.java diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8PredicateChainUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8PredicateChainUnitTest.java new file mode 100644 index 0000000000..fa579f9a00 --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8PredicateChainUnitTest.java @@ -0,0 +1,131 @@ +package com.baeldung.java8; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.junit.Test; + +public class Java8PredicateChainUnitTest { + + private List names = Arrays.asList("Adam", "Alexander", "John", "Tom"); + + @Test + public void whenFilterList_thenSuccess() { + List result = names.stream() + .filter(name -> name.startsWith("A")) + .collect(Collectors.toList()); + + assertEquals(2, result.size()); + assertThat(result, contains("Adam", "Alexander")); + } + + @Test + public void whenFilterListWithMultipleFilters_thenSuccess() { + List result = names.stream() + .filter(name -> name.startsWith("A")) + .filter(name -> name.length() < 5) + .collect(Collectors.toList()); + + assertEquals(1, result.size()); + assertThat(result, contains("Adam")); + } + + @Test + public void whenFilterListWithComplexPredicate_thenSuccess() { + List result = names.stream() + .filter(name -> name.startsWith("A") && name.length() < 5) + .collect(Collectors.toList()); + + assertEquals(1, result.size()); + assertThat(result, contains("Adam")); + } + + @Test + public void whenFilterListWithCombinedPredicatesInline_thenSuccess() { + List result = names.stream() + .filter(((Predicate) name -> name.startsWith("A")).and(name -> name.length() < 5)) + .collect(Collectors.toList()); + + assertEquals(1, result.size()); + assertThat(result, contains("Adam")); + } + + @Test + public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess() { + Predicate predicate1 = str -> str.startsWith("A"); + Predicate predicate2 = str -> str.length() < 5; + + List result = names.stream() + .filter(predicate1.and(predicate2)) + .collect(Collectors.toList()); + + assertEquals(1, result.size()); + assertThat(result, contains("Adam")); + } + + @Test + public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess() { + Predicate predicate1 = str -> str.startsWith("J"); + Predicate predicate2 = str -> str.length() < 4; + + List result = names.stream() + .filter(predicate1.or(predicate2)) + .collect(Collectors.toList()); + + assertEquals(2, result.size()); + assertThat(result, contains("John", "Tom")); + } + + @Test + public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess() { + Predicate predicate1 = str -> str.startsWith("J"); + Predicate predicate2 = str -> str.length() < 4; + + List result = names.stream() + .filter(predicate1.or(predicate2.negate())) + .collect(Collectors.toList()); + + assertEquals(3, result.size()); + assertThat(result, contains("Adam", "Alexander", "John")); + } + + @Test + public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess() { + List> allPredicates = new ArrayList>(); + allPredicates.add(str -> str.startsWith("A")); + allPredicates.add(str -> str.contains("d")); + allPredicates.add(str -> str.length() > 4); + + List result = names.stream() + .filter(allPredicates.stream() + .reduce(x -> true, Predicate::and)) + .collect(Collectors.toList()); + + assertEquals(1, result.size()); + assertThat(result, contains("Alexander")); + } + + @Test + public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess() { + List> allPredicates = new ArrayList>(); + allPredicates.add(str -> str.startsWith("A")); + allPredicates.add(str -> str.contains("d")); + allPredicates.add(str -> str.length() > 4); + + List result = names.stream() + .filter(allPredicates.stream() + .reduce(x -> false, Predicate::or)) + .collect(Collectors.toList()); + + assertEquals(2, result.size()); + assertThat(result, contains("Adam", "Alexander")); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java similarity index 74% rename from core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java rename to core-java-modules/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-modules/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))); + } + } diff --git a/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesLongRunningUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesLongRunningUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesLongRunningUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesLongRunningUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/UnsignedArithmeticUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/UnsignedArithmeticUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/UnsignedArithmeticUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/UnsignedArithmeticUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/comparator/Employee.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/comparator/Employee.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/comparator/Employee.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/comparator/Employee.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/comparator/Java8ComparatorUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/comparator/Java8ComparatorUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/comparator/Java8ComparatorUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/comparator/Java8ComparatorUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/entity/Human.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/entity/Human.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/entity/Human.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/entity/Human.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java new file mode 100644 index 0000000000..26f9f8bc46 --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java @@ -0,0 +1,34 @@ +package com.baeldung.java8.lambda.methodreference; + +public class Bicycle { + + private String brand; + private Integer frameSize; + + public Bicycle(String brand) { + this.brand = brand; + this.frameSize = 0; + } + + public Bicycle(String brand, Integer frameSize) { + this.brand = brand; + this.frameSize = frameSize; + } + + public String getBrand() { + return brand; + } + + public void setBrand(String brand) { + this.brand = brand; + } + + public Integer getFrameSize() { + return frameSize; + } + + public void setFrameSize(Integer frameSize) { + this.frameSize = frameSize; + } + +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java new file mode 100644 index 0000000000..153a7d105a --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java @@ -0,0 +1,13 @@ +package com.baeldung.java8.lambda.methodreference; + +import java.util.Comparator; + +public class BicycleComparator implements Comparator { + + @Override + public int compare(Bicycle a, Bicycle b) { + return a.getFrameSize() + .compareTo(b.getFrameSize()); + } + +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java new file mode 100644 index 0000000000..835815aecd --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.java8.lambda.methodreference; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiFunction; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +public class MethodReferenceUnitTest { + + private static void doNothingAtAll(Object... o) { + } + + ; + + @Test + public void referenceToStaticMethod() { + List messages = Arrays.asList("Hello", "Baeldung", "readers!"); + messages.forEach(word -> StringUtils.capitalize(word)); + messages.forEach(StringUtils::capitalize); + } + + @Test + public void referenceToInstanceMethodOfParticularObject() { + BicycleComparator bikeFrameSizeComparator = new BicycleComparator(); + createBicyclesList().stream() + .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b)); + createBicyclesList().stream() + .sorted(bikeFrameSizeComparator::compare); + } + + @Test + public void referenceToInstanceMethodOfArbitratyObjectOfParticularType() { + List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18); + numbers.stream() + .sorted((a, b) -> Integer.compare(a, b)); + numbers.stream() + .sorted(Integer::compare); + } + + @Test + public void referenceToConstructor() { + BiFunction bikeCreator = (brand, frameSize) -> new Bicycle(brand, frameSize); + BiFunction bikeCreatorMethodReference = Bicycle::new; + List bikes = new ArrayList<>(); + bikes.add(bikeCreator.apply("Giant", 50)); + bikes.add(bikeCreator.apply("Scott", 20)); + bikes.add(bikeCreatorMethodReference.apply("Trek", 35)); + bikes.add(bikeCreatorMethodReference.apply("GT", 40)); + } + + @Test + public void referenceToConstructorSimpleExample() { + List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT"); + bikeBrands.stream() + .map(Bicycle::new) + .toArray(Bicycle[]::new); + } + + @Test + public void limitationsAndAdditionalExamples() { + createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize())); + createBicyclesList().forEach((o) -> MethodReferenceUnitTest.doNothingAtAll(o)); + } + + private List createBicyclesList() { + List bikes = new ArrayList<>(); + bikes.add(new Bicycle("Giant", 50)); + bikes.add(new Bicycle("Scott", 20)); + bikes.add(new Bicycle("Trek", 35)); + bikes.add(new Bicycle("GT", 40)); + return bikes; + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java similarity index 93% rename from core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java index 13ddcc805f..b409f8e37f 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java @@ -1,8 +1,8 @@ -package com.baeldung.java8; +package com.baeldung.java8.lambda.tips; -import com.baeldung.Foo; -import com.baeldung.FooExtended; -import com.baeldung.UseFoo; +import com.baeldung.java8.lambda.tips.Foo; +import com.baeldung.java8.lambda.tips.FooExtended; +import com.baeldung.java8.lambda.tips.UseFoo; import org.junit.Before; import org.junit.Test; diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java new file mode 100644 index 0000000000..3e0d752bb6 --- /dev/null +++ b/core-java-modules/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 || "".equals(input) || "empty".equals(input)) { + return Optional.empty(); + } + + return Optional.of(input); + } +} \ No newline at end of file diff --git a/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java similarity index 97% rename from core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java index 4cb2551fae..bd7943c77b 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalUnitTest.java @@ -27,34 +27,35 @@ public class OptionalUnitTest { @Test public void givenNonNull_whenCreatesNonNullable_thenCorrect() { String name = "baeldung"; - Optional.of(name); + Optional opt = Optional.of(name); + assertTrue(opt.isPresent()); } @Test(expected = NullPointerException.class) public void givenNull_whenThrowsErrorOnCreate_thenCorrect() { String name = null; - Optional opt = Optional.of(name); + Optional.of(name); } @Test public void givenNonNull_whenCreatesOptional_thenCorrect() { String name = "baeldung"; Optional opt = Optional.of(name); - assertEquals("Optional[baeldung]", opt.toString()); + assertTrue(opt.isPresent()); } @Test public void givenNonNull_whenCreatesNullable_thenCorrect() { String name = "baeldung"; Optional opt = Optional.ofNullable(name); - assertEquals("Optional[baeldung]", opt.toString()); + assertTrue(opt.isPresent()); } @Test public void givenNull_whenCreatesNullable_thenCorrect() { String name = null; Optional opt = Optional.ofNullable(name); - assertEquals("Optional.empty", opt.toString()); + assertFalse(opt.isPresent()); } // Checking Value With isPresent() diff --git a/core-java-8/src/test/java/com/baeldung/java8/optional/OrElseAndOrElseGetUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OrElseAndOrElseGetUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/optional/OrElseAndOrElseGetUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OrElseAndOrElseGetUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/math/MathNewMethodsUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/math/MathNewMethodsUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/math/MathNewMethodsUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/math/MathNewMethodsUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/optional/PersonRepositoryUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/optional/PersonRepositoryUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/optional/PersonRepositoryUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/optional/PersonRepositoryUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java similarity index 80% rename from core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java index fa351930d8..1ff34bee89 100644 --- a/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java @@ -29,4 +29,11 @@ public class CalculatorUnitTest { int result = calculator.calculate(new AddCommand(3, 7)); assertEquals(10, result); } + + @Test + public void whenCalculateUsingFactory_thenReturnCorrectResult() { + Calculator calculator = new Calculator(); + int result = calculator.calculateUsingFactory(3, 4, "add"); + assertEquals(7, result); + } } diff --git a/core-java-8/src/test/java/com/baeldung/reduceIfelse/RuleEngineUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/reduceIfelse/RuleEngineUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/reduceIfelse/RuleEngineUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/reduceIfelse/RuleEngineUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java similarity index 97% rename from core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java index b191c94826..dadd6d7543 100644 --- a/core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/reflect/MethodParamNameUnitTest.java @@ -1,34 +1,34 @@ -package com.baeldung.reflect; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.lang.reflect.Parameter; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import org.junit.Test; - -public class MethodParamNameUnitTest { - - @Test - public void whenGetConstructorParams_thenOk() - throws NoSuchMethodException, SecurityException { - List parameters - = Arrays.asList(Person.class.getConstructor(String.class).getParameters()); - Optional parameter - = parameters.stream().filter(Parameter::isNamePresent).findFirst(); - assertThat(parameter.get().getName()).isEqualTo("fullName"); - } - - @Test - public void whenGetMethodParams_thenOk() - throws NoSuchMethodException, SecurityException { - List parameters - = Arrays.asList( - Person.class.getMethod("setFullName", String.class).getParameters()); - Optional parameter - = parameters.stream().filter(Parameter::isNamePresent).findFirst(); - assertThat(parameter.get().getName()).isEqualTo("fullName"); - } -} +package com.baeldung.reflect; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import org.junit.Test; + +public class MethodParamNameUnitTest { + + @Test + public void whenGetConstructorParams_thenOk() + throws NoSuchMethodException, SecurityException { + List parameters + = Arrays.asList(Person.class.getConstructor(String.class).getParameters()); + Optional parameter + = parameters.stream().filter(Parameter::isNamePresent).findFirst(); + assertThat(parameter.get().getName()).isEqualTo("fullName"); + } + + @Test + public void whenGetMethodParams_thenOk() + throws NoSuchMethodException, SecurityException { + List parameters + = Arrays.asList( + Person.class.getMethod("setFullName", String.class).getParameters()); + Optional parameter + = parameters.stream().filter(Parameter::isNamePresent).findFirst(); + assertThat(parameter.get().getName()).isEqualTo("fullName"); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java similarity index 97% rename from core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java index 81fad12eb0..6981898500 100644 --- a/core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/spliteratorAPI/ExecutorUnitTest.java @@ -1,44 +1,44 @@ -package com.baeldung.spliteratorAPI; - -import java.util.Arrays; -import java.util.Spliterator; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import static org.assertj.core.api.Assertions.*; -import org.junit.Before; -import org.junit.Test; - -public class ExecutorUnitTest { - Article article; - Stream stream; - Spliterator spliterator; - Spliterator
split1; - Spliterator
split2; - - @Before - public void init() { - article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), - new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), - new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), - new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), - new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), - new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0); - stream = article.getListOfAuthors().stream(); - split1 = Executor.generateElements().spliterator(); - split2 = split1.trySplit(); - spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors()); - } - - @Test - public void givenAstreamOfAuthors_whenProcessedInParallelWithCustomSpliterator_coubtProducessRightOutput() { - Stream stream2 = StreamSupport.stream(spliterator, true); - assertThat(Executor.countAutors(stream2.parallel())).isEqualTo(9); - } - - @Test - public void givenSpliterator_whenAppliedToAListOfArticle_thenSplittedInHalf() { - assertThat(new Task(split1).call()).containsSequence(Executor.generateElements().size() / 2 + ""); - assertThat(new Task(split2).call()).containsSequence(Executor.generateElements().size() / 2 + ""); - } -} +package com.baeldung.spliteratorAPI; + +import java.util.Arrays; +import java.util.Spliterator; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import static org.assertj.core.api.Assertions.*; +import org.junit.Before; +import org.junit.Test; + +public class ExecutorUnitTest { + Article article; + Stream stream; + Spliterator spliterator; + Spliterator
split1; + Spliterator
split2; + + @Before + public void init() { + article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), + new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), + new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), + new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), + new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), + new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0); + stream = article.getListOfAuthors().stream(); + split1 = Executor.generateElements().spliterator(); + split2 = split1.trySplit(); + spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors()); + } + + @Test + public void givenAstreamOfAuthors_whenProcessedInParallelWithCustomSpliterator_coubtProducessRightOutput() { + Stream stream2 = StreamSupport.stream(spliterator, true); + assertThat(Executor.countAutors(stream2.parallel())).isEqualTo(9); + } + + @Test + public void givenSpliterator_whenAppliedToAListOfArticle_thenSplittedInHalf() { + assertThat(new Task(split1).call()).containsSequence(Executor.generateElements().size() / 2 + ""); + assertThat(new Task(split2).call()).containsSequence(Executor.generateElements().size() / 2 + ""); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/stream/conditional/StreamForEachIfElseUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/stream/conditional/StreamForEachIfElseUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/stream/conditional/StreamForEachIfElseUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/stream/conditional/StreamForEachIfElseUnitTest.java diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java new file mode 100644 index 0000000000..0bf1a5837e --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.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 StreamReduceManualTest { + + @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); + } +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java new file mode 100644 index 0000000000..8400748710 --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.time; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.mockStatic; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ Instant.class }) +public class InstantUnitTest { + + @Test + public void givenInstantMock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-22T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + Instant instant = Instant.now(clock); + mockStatic(Instant.class); + when(Instant.now()).thenReturn(instant); + + Instant now = Instant.now(); + + assertThat(now.toString()).isEqualTo(instantExpected); + } + + @Test + public void givenFixedClock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-22T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + + Instant instant = Instant.now(clock); + + assertThat(instant.toString()).isEqualTo(instantExpected); + } +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java new file mode 100644 index 0000000000..8f83b91101 --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.time; + +import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; +import org.junit.jupiter.api.Test; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; + +public class InstantWithJMockUnitTest { + + @Test + public void givenInstantWithJMock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-21T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + new MockUp() { + @Mock + public Instant now() { + return Instant.now(clock); + } + }; + + Instant now = Instant.now(); + + assertThat(now.toString()).isEqualTo(instantExpected); + } + + @Test + public void givenInstantWithExpectations_whenNow_thenGetFixedInstant() { + Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC")); + Instant instantExpected = Instant.now(clock); + new Expectations(Instant.class) { + { + Instant.now(); + result = instantExpected; + } + }; + + Instant now = Instant.now(); + + assertThat(now).isEqualTo(instantExpected); + } +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java new file mode 100644 index 0000000000..04c1a0b74e --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.time; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.time.Clock; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.mockStatic; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ LocalDateTime.class }) +public class LocalDateTimeUnitTest { + + @Test + public void givenLocalDateTimeMock_whenNow_thenGetFixedLocalDateTime() { + Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC")); + LocalDateTime dateTime = LocalDateTime.now(clock); + mockStatic(LocalDateTime.class); + when(LocalDateTime.now()).thenReturn(dateTime); + String dateTimeExpected = "2014-12-22T10:15:30"; + + LocalDateTime now = LocalDateTime.now(); + + assertThat(now).isEqualTo(dateTimeExpected); + } + + @Test + public void givenFixedClock_whenNow_thenGetFixedLocalDateTime() { + Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC")); + String dateTimeExpected = "2014-12-22T10:15:30"; + + LocalDateTime dateTime = LocalDateTime.now(clock); + + assertThat(dateTime).isEqualTo(dateTimeExpected); + } +} diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java new file mode 100644 index 0000000000..13861dfd0b --- /dev/null +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.time; + +import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; +import org.junit.jupiter.api.Test; + +import java.time.Clock; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LocalDateTimeWithJMockUnitTest { + + @Test + public void givenLocalDateTimeWithJMock_whenNow_thenGetFixedLocalDateTime() { + Clock clock = Clock.fixed(Instant.parse("2014-12-21T10:15:30.00Z"), ZoneId.of("UTC")); + new MockUp() { + @Mock + public LocalDateTime now() { + return LocalDateTime.now(clock); + } + }; + String dateTimeExpected = "2014-12-21T10:15:30"; + + LocalDateTime now = LocalDateTime.now(); + + assertThat(now).isEqualTo(dateTimeExpected); + } + + @Test + public void givenLocalDateTimeWithExpectations_whenNow_thenGetFixedLocalDateTime() { + Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC")); + LocalDateTime dateTimeExpected = LocalDateTime.now(clock); + new Expectations(LocalDateTime.class) { + { + LocalDateTime.now(); + result = dateTimeExpected; + } + }; + + LocalDateTime now = LocalDateTime.now(); + + assertThat(now).isEqualTo(dateTimeExpected); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/typeinference/TypeInferenceUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/typeinference/TypeInferenceUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/typeinference/TypeInferenceUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/typeinference/TypeInferenceUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeUnitTest.java rename to core-java-modules/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeUnitTest.java diff --git a/core-java-8/src/test/resources/.gitignore b/core-java-modules/core-java-8/src/test/resources/.gitignore similarity index 100% rename from core-java-8/src/test/resources/.gitignore rename to core-java-modules/core-java-8/src/test/resources/.gitignore diff --git a/core-java-9/.gitignore b/core-java-modules/core-java-9/.gitignore similarity index 100% rename from core-java-9/.gitignore rename to core-java-modules/core-java-9/.gitignore diff --git a/core-java-modules/core-java-9/README.md b/core-java-modules/core-java-9/README.md new file mode 100644 index 0000000000..8b52ce79b4 --- /dev/null +++ b/core-java-modules/core-java-9/README.md @@ -0,0 +1,33 @@ +========= + +## Core Java 9 Examples + +[Java 9 New Features](http://www.baeldung.com/new-java-9) + +### Relevant Articles: + +- [Java 9 New Features](https://www.baeldung.com/new-java-9) +- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) +- [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity) +- [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles) +- [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) +- [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional) +- [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) +- [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) +- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new) +- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams) +- [Java 9 Optional API Additions](https://www.baeldung.com/java-9-optional) +- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture) +- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api) +- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods) +- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api) +- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity) +- [Java 9 java.lang.Module API](https://www.baeldung.com/java-9-module-api) +- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) +- [Filtering a Stream of Optionals in Java](https://www.baeldung.com/java-filter-stream-of-optional) diff --git a/core-java-modules/core-java-9/compile-aot.sh b/core-java-modules/core-java-9/compile-aot.sh new file mode 100644 index 0000000000..c3a39b0196 --- /dev/null +++ b/core-java-modules/core-java-9/compile-aot.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +cd src/main/java +javac com/baeldung/java9/aot/JaotCompilation.java +jaotc --output jaotCompilation.so com/baeldung/java9/aot/JaotCompilation.class + diff --git a/core-java-9/compile-httpclient.bat b/core-java-modules/core-java-9/compile-httpclient.bat similarity index 100% rename from core-java-9/compile-httpclient.bat rename to core-java-modules/core-java-9/compile-httpclient.bat diff --git a/core-java-9/compile-modules.sh b/core-java-modules/core-java-9/compile-modules.sh old mode 100755 new mode 100644 similarity index 100% rename from core-java-9/compile-modules.sh rename to core-java-modules/core-java-9/compile-modules.sh diff --git a/core-java-9/compile-simple-modules.sh b/core-java-modules/core-java-9/compile-simple-modules.sh old mode 100755 new mode 100644 similarity index 100% rename from core-java-9/compile-simple-modules.sh rename to core-java-modules/core-java-9/compile-simple-modules.sh diff --git a/core-java-9/compile-student-client.bat b/core-java-modules/core-java-9/compile-student-client.bat similarity index 100% rename from core-java-9/compile-student-client.bat rename to core-java-modules/core-java-9/compile-student-client.bat diff --git a/core-java-9/compile-student-model.bat b/core-java-modules/core-java-9/compile-student-model.bat similarity index 100% rename from core-java-9/compile-student-model.bat rename to core-java-modules/core-java-9/compile-student-model.bat diff --git a/core-java-9/compile-student-service-dbimpl.bat b/core-java-modules/core-java-9/compile-student-service-dbimpl.bat similarity index 100% rename from core-java-9/compile-student-service-dbimpl.bat rename to core-java-modules/core-java-9/compile-student-service-dbimpl.bat diff --git a/core-java-9/compile-student-service.bat b/core-java-modules/core-java-9/compile-student-service.bat similarity index 100% rename from core-java-9/compile-student-service.bat rename to core-java-modules/core-java-9/compile-student-service.bat diff --git a/core-java-9/logging.sh b/core-java-modules/core-java-9/logging.sh old mode 100755 new mode 100644 similarity index 100% rename from core-java-9/logging.sh rename to core-java-modules/core-java-9/logging.sh diff --git a/core-java-9/mods/logback.xml b/core-java-modules/core-java-9/mods/logback.xml similarity index 100% rename from core-java-9/mods/logback.xml rename to core-java-modules/core-java-9/mods/logback.xml diff --git a/core-java-9/pom.xml b/core-java-modules/core-java-9/pom.xml similarity index 98% rename from core-java-9/pom.xml rename to core-java-modules/core-java-9/pom.xml index cd1fa74dbb..aee289c79f 100644 --- a/core-java-9/pom.xml +++ b/core-java-modules/core-java-9/pom.xml @@ -9,6 +9,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../../ diff --git a/core-java-modules/core-java-9/run-aot.sh b/core-java-modules/core-java-9/run-aot.sh new file mode 100644 index 0000000000..89fc616469 --- /dev/null +++ b/core-java-modules/core-java-9/run-aot.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +cd src/main/java +java -XX:AOTLibrary=./jaotCompilation.so com/baeldung/java9/aot/JaotCompilation \ No newline at end of file diff --git a/core-java-9/run-httpclient.bat b/core-java-modules/core-java-9/run-httpclient.bat similarity index 100% rename from core-java-9/run-httpclient.bat rename to core-java-modules/core-java-9/run-httpclient.bat diff --git a/core-java-9/run-simple-module-app.sh b/core-java-modules/core-java-9/run-simple-module-app.sh old mode 100755 new mode 100644 similarity index 100% rename from core-java-9/run-simple-module-app.sh rename to core-java-modules/core-java-9/run-simple-module-app.sh diff --git a/core-java-9/run-student-client.bat b/core-java-modules/core-java-9/run-student-client.bat similarity index 100% rename from core-java-9/run-student-client.bat rename to core-java-modules/core-java-9/run-student-client.bat diff --git a/core-java-9/run-student-client.sh b/core-java-modules/core-java-9/run-student-client.sh old mode 100755 new mode 100644 similarity index 100% rename from core-java-9/run-student-client.sh rename to core-java-modules/core-java-9/run-student-client.sh diff --git a/core-java-9/src/main/java/.gitignore b/core-java-modules/core-java-9/src/main/java/.gitignore similarity index 100% rename from core-java-9/src/main/java/.gitignore rename to core-java-modules/core-java-9/src/main/java/.gitignore diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java new file mode 100644 index 0000000000..4d8a018d6b --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java @@ -0,0 +1,12 @@ +package com.baeldung.java9.aot; + +public class JaotCompilation { + + public static void main(String[] argv) { + System.out.println(message()); + } + + public static String message() { + return "The JAOT compiler says 'Hello'"; + } +} \ No newline at end of file diff --git a/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java similarity index 96% rename from core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java index f7b2fad891..3055f82fdb 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java @@ -1,23 +1,23 @@ -package com.baeldung.java9.language; - -public interface PrivateInterface { - - private static String staticPrivate() { - return "static private"; - } - - private String instancePrivate() { - return "instance private"; - } - - public default void check() { - String result = staticPrivate(); - if (!result.equals("static private")) - throw new AssertionError("Incorrect result for static private interface method"); - PrivateInterface pvt = new PrivateInterface() { - }; - result = pvt.instancePrivate(); - if (!result.equals("instance private")) - throw new AssertionError("Incorrect result for instance private interface method"); - } -} +package com.baeldung.java9.language; + +public interface PrivateInterface { + + private static String staticPrivate() { + return "static private"; + } + + private String instancePrivate() { + return "instance private"; + } + + public default void check() { + String result = staticPrivate(); + if (!result.equals("static private")) + throw new AssertionError("Incorrect result for static private interface method"); + PrivateInterface pvt = new PrivateInterface() { + }; + result = pvt.instancePrivate(); + if (!result.equals("instance private")) + throw new AssertionError("Incorrect result for instance private interface method"); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/methodhandles/Book.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/methodhandles/Book.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/methodhandles/Book.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/methodhandles/Book.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/rangedates/DatesCollectionIteration.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/rangedates/DatesCollectionIteration.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/rangedates/DatesCollectionIteration.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/rangedates/DatesCollectionIteration.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/rangedates/RangeDatesIteration.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/rangedates/RangeDatesIteration.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/rangedates/RangeDatesIteration.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/rangedates/RangeDatesIteration.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java similarity index 96% rename from core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java index 46eee4883a..962df447b6 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java @@ -1,82 +1,82 @@ -package com.baeldung.java9.reactive; - -import java.util.ArrayList; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -public class BaeldungBatchSubscriberImpl implements Subscriber { - private Subscription subscription; - private boolean completed = false; - private int counter; - private ArrayList buffer; - public static final int BUFFER_SIZE = 5; - - public BaeldungBatchSubscriberImpl() { - buffer = new ArrayList(); - } - - public boolean isCompleted() { - return completed; - } - - public void setCompleted(boolean completed) { - this.completed = completed; - } - - public int getCounter() { - return counter; - } - - public void setCounter(int counter) { - this.counter = counter; - } - - @Override - public void onSubscribe(Subscription subscription) { - this.subscription = subscription; - subscription.request(BUFFER_SIZE); - } - - @Override - public void onNext(String item) { - buffer.add(item); - // if buffer is full, process the items. - if (buffer.size() >= BUFFER_SIZE) { - processBuffer(); - } - //request more items. - subscription.request(1); - } - - private void processBuffer() { - if (buffer.isEmpty()) - return; - // Process all items in the buffer. Here, we just print it and sleep for 1 second. - System.out.print("Processed items: "); - buffer.stream() - .forEach(item -> { - System.out.print(" " + item); - }); - System.out.println(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - counter = counter + buffer.size(); - buffer.clear(); - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - } - - @Override - public void onComplete() { - completed = true; - // process any remaining items in buffer before - processBuffer(); - subscription.cancel(); - } -} +package com.baeldung.java9.reactive; + +import java.util.ArrayList; +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + +public class BaeldungBatchSubscriberImpl implements Subscriber { + private Subscription subscription; + private boolean completed = false; + private int counter; + private ArrayList buffer; + public static final int BUFFER_SIZE = 5; + + public BaeldungBatchSubscriberImpl() { + buffer = new ArrayList(); + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + @Override + public void onSubscribe(Subscription subscription) { + this.subscription = subscription; + subscription.request(BUFFER_SIZE); + } + + @Override + public void onNext(String item) { + buffer.add(item); + // if buffer is full, process the items. + if (buffer.size() >= BUFFER_SIZE) { + processBuffer(); + } + //request more items. + subscription.request(1); + } + + private void processBuffer() { + if (buffer.isEmpty()) + return; + // Process all items in the buffer. Here, we just print it and sleep for 1 second. + System.out.print("Processed items: "); + buffer.stream() + .forEach(item -> { + System.out.print(" " + item); + }); + System.out.println(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + counter = counter + buffer.size(); + buffer.clear(); + } + + @Override + public void onError(Throwable t) { + t.printStackTrace(); + } + + @Override + public void onComplete() { + completed = true; + // process any remaining items in buffer before + processBuffer(); + subscription.cancel(); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java similarity index 95% rename from core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java index bacd777255..3534324675 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java @@ -1,55 +1,55 @@ -package com.baeldung.java9.reactive; - -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -public class BaeldungSubscriberImpl implements Subscriber { - private Subscription subscription; - private boolean completed = false; - private int counter; - - public boolean isCompleted() { - return completed; - } - - public void setCompleted(boolean completed) { - this.completed = completed; - } - - public int getCounter() { - return counter; - } - - public void setCounter(int counter) { - this.counter = counter; - } - - @Override - public void onSubscribe(Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - counter++; - System.out.println("Processed item : " + item); - subscription.request(1); - } - - @Override - public void onError(Throwable t) { - t.printStackTrace(); - } - - @Override - public void onComplete() { - completed = true; - subscription.cancel(); - } -} +package com.baeldung.java9.reactive; + +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + +public class BaeldungSubscriberImpl implements Subscriber { + private Subscription subscription; + private boolean completed = false; + private int counter; + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + @Override + public void onSubscribe(Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(String item) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + counter++; + System.out.println("Processed item : " + item); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + t.printStackTrace(); + } + + @Override + public void onComplete() { + completed = true; + subscription.cancel(); + } +} diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java new file mode 100644 index 0000000000..7dbcd2a3a3 --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java @@ -0,0 +1,44 @@ +package com.baeldung.java9.set; + +import com.google.common.collect.ImmutableSet; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class UnmodifiableSet { + + public static void main(String[] args) { + + Set set = new HashSet<>(); + set.add("Canada"); + set.add("USA"); + + coreJDK(set); + guavaOf(); + copyOf(set); + java9Of(); + } + + private static void java9Of() { + Set immutable = Set.of("Canada", "USA"); + System.out.println(immutable); + } + + private static void guavaOf() { + Set immutable = ImmutableSet.of("Canada", "USA"); + System.out.println(immutable); + } + + private static void copyOf(Set set) { + Set immutable = ImmutableSet.copyOf(set); + set.add("Costa Rica"); + System.out.println(immutable); + } + + private static void coreJDK(Set set) { + Set unmodifiableSet = Collections.unmodifiableSet(set); + set.add("Costa Rica"); + System.out.println(unmodifiableSet); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/EndSubscriber.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/streams.reactive/TransformProcessor.java diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java new file mode 100644 index 0000000000..21bbcc01d4 --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java @@ -0,0 +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); + logger.info("Date given " + dateToCheck + " is leap year: " + isLeapYear); + } + +} diff --git a/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java new file mode 100644 index 0000000000..4d943db30b --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java @@ -0,0 +1,22 @@ +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 { + 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); + return (new GregorianCalendar()).isLeapYear(year); + } + +} diff --git a/core-java-9/src/main/java/com/baeldung/optionals/Optionals.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/optionals/Optionals.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/optionals/Optionals.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/optionals/Optionals.java diff --git a/core-java-modules/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java b/core-java-modules/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java new file mode 100644 index 0000000000..35fb0ada1e --- /dev/null +++ b/core-java-modules/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java @@ -0,0 +1,18 @@ +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 { + logger.info("Checking for leap year using Java 9 Date Api"); + return LocalDate.parse(dateStr) + .isLeapYear(); + } + +} diff --git a/core-java-9/src/main/resources/logback.xml b/core-java-modules/core-java-9/src/main/resources/logback.xml similarity index 100% rename from core-java-9/src/main/resources/logback.xml rename to core-java-modules/core-java-9/src/main/resources/logback.xml diff --git a/core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java b/core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/com/baeldung/httpclient/HttpClientExample.java diff --git a/core-java-9/src/modules/com.baeldung.httpclient/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.httpclient/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.httpclient/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java diff --git a/core-java-9/src/modules/com.baeldung.logging.app/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging.app/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging.app/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java similarity index 87% rename from core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java index df41e071fd..db19613c94 100644 --- a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java +++ b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ResourceBundle; +import java.text.MessageFormat; public class Slf4jLogger implements System.Logger { @@ -74,26 +75,27 @@ public class Slf4jLogger implements System.Logger { if (!isLoggable(level)) { return; } + String message = MessageFormat.format(format, params); switch (level) { case TRACE: - logger.trace(format, params); + logger.trace(message); break; case DEBUG: - logger.debug(format, params); + logger.debug(message); break; case INFO: - logger.info(format, params); + logger.info(message); break; case WARNING: - logger.warn(format, params); + logger.warn(message); break; case ERROR: - logger.error(format, params); + logger.error(message); break; case ALL: default: - logger.info(format, params); + logger.info(message); } } } diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java diff --git a/core-java-9/src/modules/com.baeldung.logging/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.logging/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.logging/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java diff --git a/core-java-9/src/modules/com.baeldung.student.client/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.client/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.client/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.client/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java diff --git a/core-java-9/src/modules/com.baeldung.student.model/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.model/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.model/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.model/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java diff --git a/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java diff --git a/core-java-9/src/modules/com.baeldung.student.service/module-info.java b/core-java-modules/core-java-9/src/modules/com.baeldung.student.service/module-info.java similarity index 100% rename from core-java-9/src/modules/com.baeldung.student.service/module-info.java rename to core-java-modules/core-java-9/src/modules/com.baeldung.student.service/module-info.java diff --git a/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java b/core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java similarity index 100% rename from core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java rename to core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloInterface.java diff --git a/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java b/core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java similarity index 100% rename from core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java rename to core-java-modules/core-java-9/src/simple-modules/hello.modules/com/baeldung/modules/hello/HelloModules.java diff --git a/core-java-9/src/simple-modules/hello.modules/module-info.java b/core-java-modules/core-java-9/src/simple-modules/hello.modules/module-info.java similarity index 100% rename from core-java-9/src/simple-modules/hello.modules/module-info.java rename to core-java-modules/core-java-9/src/simple-modules/hello.modules/module-info.java diff --git a/core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java b/core-java-modules/core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java similarity index 100% rename from core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java rename to core-java-modules/core-java-9/src/simple-modules/main.app/com/baeldung/modules/main/MainApp.java diff --git a/core-java-9/src/simple-modules/main.app/module-info.java b/core-java-modules/core-java-9/src/simple-modules/main.app/module-info.java similarity index 100% rename from core-java-9/src/simple-modules/main.app/module-info.java rename to core-java-modules/core-java-9/src/simple-modules/main.app/module-info.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java similarity index 97% rename from core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java index 2c383a44b4..442d85e3f2 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageUnitTest.java @@ -1,44 +1,44 @@ -package com.baeldung.java9; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - -import java.awt.Image; -import java.awt.image.BaseMultiResolutionImage; -import java.awt.image.BufferedImage; -import java.awt.image.MultiResolutionImage; -import java.util.List; - -import org.junit.Test; - -public class MultiResultionImageUnitTest { - - @Test - public void baseMultiResImageTest() { - int baseIndex = 1; - int length = 4; - BufferedImage[] resolutionVariants = new BufferedImage[length]; - for (int i = 0; i < length; i++) { - resolutionVariants[i] = createImage(i); - } - MultiResolutionImage bmrImage = new BaseMultiResolutionImage(baseIndex, resolutionVariants); - List rvImageList = bmrImage.getResolutionVariants(); - assertEquals("MultiResoltion Image shoudl contain the same number of resolution variants!", rvImageList.size(), length); - - for (int i = 0; i < length; i++) { - int imageSize = getSize(i); - Image testRVImage = bmrImage.getResolutionVariant(imageSize, imageSize); - assertSame("Images should be the same", testRVImage, resolutionVariants[i]); - } - - } - - private static int getSize(int i) { - return 8 * (i + 1); - } - - private static BufferedImage createImage(int i) { - return new BufferedImage(getSize(i), getSize(i), BufferedImage.TYPE_INT_RGB); - } - -} +package com.baeldung.java9; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.awt.Image; +import java.awt.image.BaseMultiResolutionImage; +import java.awt.image.BufferedImage; +import java.awt.image.MultiResolutionImage; +import java.util.List; + +import org.junit.Test; + +public class MultiResultionImageUnitTest { + + @Test + public void baseMultiResImageTest() { + int baseIndex = 1; + int length = 4; + BufferedImage[] resolutionVariants = new BufferedImage[length]; + for (int i = 0; i < length; i++) { + resolutionVariants[i] = createImage(i); + } + MultiResolutionImage bmrImage = new BaseMultiResolutionImage(baseIndex, resolutionVariants); + List rvImageList = bmrImage.getResolutionVariants(); + assertEquals("MultiResoltion Image shoudl contain the same number of resolution variants!", rvImageList.size(), length); + + for (int i = 0; i < length; i++) { + int imageSize = getSize(i); + Image testRVImage = bmrImage.getResolutionVariant(imageSize, imageSize); + assertSame("Images should be the same", testRVImage, resolutionVariants[i]); + } + + } + + private static int getSize(int i) { + return 8 * (i + 1); + } + + private static BufferedImage createImage(int i) { + return new BufferedImage(getSize(i), getSize(i), BufferedImage.TYPE_INT_RGB); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/README.MD b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/README.MD similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/README.MD rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/README.MD diff --git a/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java similarity index 64% rename from core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java index 9e7e8e6e4b..28e71affcc 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java @@ -1,5 +1,7 @@ package com.baeldung.java9; +import java.util.Collections; +import java.util.HashSet; import java.util.Set; import org.junit.Test; @@ -23,4 +25,14 @@ public class SetExamplesUnitTest { Set intSet = Set.of(intArray); assertEquals(intSet.size(), intArray.length); } + + @Test(expected = UnsupportedOperationException.class) + public void testUnmodifiableSet() { + Set set = new HashSet<>(); + set.add("Canada"); + set.add("USA"); + + Set unmodifiableSet = Collections.unmodifiableSet(set); + unmodifiableSet.add("Costa Rica"); + } } diff --git a/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java similarity index 95% rename from core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java index 4868d37b6a..b1cb4ef63b 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/DiamondUnitTest.java @@ -1,36 +1,36 @@ -package com.baeldung.java9.language; - -import org.junit.Test; - -public class DiamondUnitTest { - - static class FooClass { - FooClass(X x) { - } - - FooClass(X x, Z z) { - } - } - - @Test - public void diamondTest() { - FooClass fc = new FooClass<>(1) { - }; - FooClass fc0 = new FooClass<>(1) { - }; - FooClass fc1 = new FooClass<>(1) { - }; - FooClass fc2 = new FooClass<>(1) { - }; - - FooClass fc3 = new FooClass<>(1, "") { - }; - FooClass fc4 = new FooClass<>(1, "") { - }; - FooClass fc5 = new FooClass<>(1, "") { - }; - FooClass fc6 = new FooClass<>(1, "") { - }; - - } -} +package com.baeldung.java9.language; + +import org.junit.Test; + +public class DiamondUnitTest { + + static class FooClass { + FooClass(X x) { + } + + FooClass(X x, Z z) { + } + } + + @Test + public void diamondTest() { + FooClass fc = new FooClass<>(1) { + }; + FooClass fc0 = new FooClass<>(1) { + }; + FooClass fc1 = new FooClass<>(1) { + }; + FooClass fc2 = new FooClass<>(1) { + }; + + FooClass fc3 = new FooClass<>(1, "") { + }; + FooClass fc4 = new FooClass<>(1, "") { + }; + FooClass fc5 = new FooClass<>(1, "") { + }; + FooClass fc6 = new FooClass<>(1, "") { + }; + + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java similarity index 95% rename from core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java index fb00fe45c3..08aee72f6e 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceUnitTest.java @@ -1,15 +1,15 @@ -package com.baeldung.java9.language; - -import com.baeldung.java9.language.PrivateInterface; -import org.junit.Test; - -public class PrivateInterfaceUnitTest { - - @Test - public void test() { - PrivateInterface piClass = new PrivateInterface() { - }; - piClass.check(); - } - -} +package com.baeldung.java9.language; + +import com.baeldung.java9.language.PrivateInterface; +import org.junit.Test; + +public class PrivateInterfaceUnitTest { + + @Test + public void test() { + PrivateInterface piClass = new PrivateInterface() { + }; + piClass.check(); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java similarity index 96% rename from core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java index d623bd9965..9afa1c90dd 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesUnitTest.java @@ -1,67 +1,67 @@ -package com.baeldung.java9.language; - -import static org.junit.Assert.assertEquals; -import org.junit.Test; - -public class TryWithResourcesUnitTest { - - static int closeCount = 0; - - static class MyAutoCloseable implements AutoCloseable { - final FinalWrapper finalWrapper = new FinalWrapper(); - - public void close() { - closeCount++; - } - - static class FinalWrapper { - public final AutoCloseable finalCloseable = new AutoCloseable() { - @Override - public void close() throws Exception { - closeCount++; - } - }; - } - } - - @Test - public void tryWithResourcesTest() { - MyAutoCloseable mac = new MyAutoCloseable(); - - try (mac) { - assertEquals("Expected and Actual does not match", 0, closeCount); - } - - try (mac.finalWrapper.finalCloseable) { - assertEquals("Expected and Actual does not match", 1, closeCount); - } catch (Exception ex) { - } - - try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) { - assertEquals("Expected and Actual does not match", 2, closeCount); - } catch (Exception ex) { - } - - try ((closeCount > 0 ? mac : new MyAutoCloseable()).finalWrapper.finalCloseable) { - assertEquals("Expected and Actual does not match", 3, closeCount); - } catch (Exception ex) { - } - - try { - throw new CloseableException(); - } catch (CloseableException ex) { - try (ex) { - assertEquals("Expected and Actual does not match", 4, closeCount); - } - } - assertEquals("Expected and Actual does not match", 5, closeCount); - } - - static class CloseableException extends Exception implements AutoCloseable { - @Override - public void close() { - closeCount++; - } - } - -} +package com.baeldung.java9.language; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class TryWithResourcesUnitTest { + + static int closeCount = 0; + + static class MyAutoCloseable implements AutoCloseable { + final FinalWrapper finalWrapper = new FinalWrapper(); + + public void close() { + closeCount++; + } + + static class FinalWrapper { + public final AutoCloseable finalCloseable = new AutoCloseable() { + @Override + public void close() throws Exception { + closeCount++; + } + }; + } + } + + @Test + public void tryWithResourcesTest() { + MyAutoCloseable mac = new MyAutoCloseable(); + + try (mac) { + assertEquals("Expected and Actual does not match", 0, closeCount); + } + + try (mac.finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 1, closeCount); + } catch (Exception ex) { + } + + try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 2, closeCount); + } catch (Exception ex) { + } + + try ((closeCount > 0 ? mac : new MyAutoCloseable()).finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 3, closeCount); + } catch (Exception ex) { + } + + try { + throw new CloseableException(); + } catch (CloseableException ex) { + try (ex) { + assertEquals("Expected and Actual does not match", 4, closeCount); + } + } + assertEquals("Expected and Actual does not match", 5, closeCount); + } + + static class CloseableException extends Exception implements AutoCloseable { + @Override + public void close() { + closeCount++; + } + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/ListFactoryMethodsUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/MapFactoryMethodsUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/collections/SetFactoryMethodsUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectorImprovementUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/methodhandles/MethodHandlesTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/methodhandles/MethodHandlesTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/methodhandles/MethodHandlesTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/methodhandles/MethodHandlesTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/rangedates/DatesCollectionIterationUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/rangedates/DatesCollectionIterationUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/rangedates/DatesCollectionIterationUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/rangedates/DatesCollectionIterationUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/rangedates/RangeDatesIterationUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/rangedates/RangeDatesIterationUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/rangedates/RangeDatesIterationUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/rangedates/RangeDatesIterationUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java similarity index 96% rename from core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java index cbc3946999..15dc13ec71 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplIntegrationTest.java @@ -1,75 +1,75 @@ -package com.baeldung.java9.reactive; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.SubmissionPublisher; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Stopwatch; - -public class BaeldungBatchSubscriberImplIntegrationTest { - - private static final int ITEM_SIZE = 10; - private SubmissionPublisher publisher; - private BaeldungBatchSubscriberImpl subscriber; - - @Before - public void initialize() { - this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 6); - this.subscriber = new BaeldungBatchSubscriberImpl(); - publisher.subscribe(subscriber); - } - - @Rule - public Stopwatch stopwatch = new Stopwatch() { - - }; - - @Test - public void testReactiveStreamCount() { - IntStream.range(0, ITEM_SIZE) - .forEach(item -> publisher.submit(item + "")); - publisher.close(); - - do { - // wait for subscribers to complete all processing. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (!subscriber.isCompleted()); - - int count = subscriber.getCounter(); - - assertEquals(ITEM_SIZE, count); - } - - @Test - public void testReactiveStreamTime() { - IntStream.range(0, ITEM_SIZE) - .forEach(item -> publisher.submit(item + "")); - publisher.close(); - - do { - // wait for subscribers to complete all processing. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (!subscriber.isCompleted()); - - // The runtime in seconds should be equal to the number of items in each batch. - assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= (ITEM_SIZE / subscriber.BUFFER_SIZE)); - } - -} +package com.baeldung.java9.reactive; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.SubmissionPublisher; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Stopwatch; + +public class BaeldungBatchSubscriberImplIntegrationTest { + + private static final int ITEM_SIZE = 10; + private SubmissionPublisher publisher; + private BaeldungBatchSubscriberImpl subscriber; + + @Before + public void initialize() { + this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 6); + this.subscriber = new BaeldungBatchSubscriberImpl(); + publisher.subscribe(subscriber); + } + + @Rule + public Stopwatch stopwatch = new Stopwatch() { + + }; + + @Test + public void testReactiveStreamCount() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + + assertEquals(ITEM_SIZE, count); + } + + @Test + public void testReactiveStreamTime() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + // The runtime in seconds should be equal to the number of items in each batch. + assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= (ITEM_SIZE / subscriber.BUFFER_SIZE)); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java similarity index 96% rename from core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java index 6fd093b362..84877db500 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java +++ b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplIntegrationTest.java @@ -1,100 +1,100 @@ -package com.baeldung.java9.reactive; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.SubmissionPublisher; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Stopwatch; - -public class BaeldungSubscriberImplIntegrationTest { - - private static final int ITEM_SIZE = 10; - private SubmissionPublisher publisher; - private BaeldungSubscriberImpl subscriber; - - @Before - public void initialize() { - // create Publisher with max buffer capacity 3. - this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 3); - this.subscriber = new BaeldungSubscriberImpl(); - publisher.subscribe(subscriber); - } - - @Rule - public Stopwatch stopwatch = new Stopwatch() { - - }; - - @Test - public void testReactiveStreamCount() { - IntStream.range(0, ITEM_SIZE) - .forEach(item -> publisher.submit(item + "")); - publisher.close(); - - do { - // wait for subscribers to complete all processing. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (!subscriber.isCompleted()); - - int count = subscriber.getCounter(); - - assertEquals(ITEM_SIZE, count); - } - - @Test - public void testReactiveStreamTime() { - IntStream.range(0, ITEM_SIZE) - .forEach(item -> publisher.submit(item + "")); - publisher.close(); - - do { - // wait for subscribers to complete all processing. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (!subscriber.isCompleted()); - - // The runtime in seconds should be equal to the number of items. - assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= ITEM_SIZE); - } - - @Test - public void testReactiveStreamOffer() { - IntStream.range(0, ITEM_SIZE) - .forEach(item -> publisher.offer(item + "", (subscriber, string) -> { - // Returning false means this item will be dropped (no retry), if blocked. - return false; - })); - publisher.close(); - - do { - // wait for subscribers to complete all processing. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (!subscriber.isCompleted()); - - int count = subscriber.getCounter(); - // Because 10 items were offered and the buffer capacity was 3, few items will not be processed. - assertTrue(ITEM_SIZE > count); - } - -} +package com.baeldung.java9.reactive; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.SubmissionPublisher; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Stopwatch; + +public class BaeldungSubscriberImplIntegrationTest { + + private static final int ITEM_SIZE = 10; + private SubmissionPublisher publisher; + private BaeldungSubscriberImpl subscriber; + + @Before + public void initialize() { + // create Publisher with max buffer capacity 3. + this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 3); + this.subscriber = new BaeldungSubscriberImpl(); + publisher.subscribe(subscriber); + } + + @Rule + public Stopwatch stopwatch = new Stopwatch() { + + }; + + @Test + public void testReactiveStreamCount() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + + assertEquals(ITEM_SIZE, count); + } + + @Test + public void testReactiveStreamTime() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + // The runtime in seconds should be equal to the number of items. + assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= ITEM_SIZE); + } + + @Test + public void testReactiveStreamOffer() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.offer(item + "", (subscriber, string) -> { + // Returning false means this item will be dropped (no retry), if blocked. + return false; + })); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + // Because 10 items were offered and the buffer capacity was 3, few items will not be processed. + assertTrue(ITEM_SIZE > count); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoUnitTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java diff --git a/core-java-9/src/test/java/com/baeldung/optionals/OptionalsTest.java b/core-java-modules/core-java-9/src/test/java/com/baeldung/optionals/OptionalsTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/optionals/OptionalsTest.java rename to core-java-modules/core-java-9/src/test/java/com/baeldung/optionals/OptionalsTest.java diff --git a/core-java-9/src/test/resources/.gitignore b/core-java-modules/core-java-9/src/test/resources/.gitignore similarity index 100% rename from core-java-9/src/test/resources/.gitignore rename to core-java-modules/core-java-9/src/test/resources/.gitignore diff --git a/core-java-lang/.gitignore b/core-java-modules/core-java-arrays/.gitignore similarity index 100% rename from core-java-lang/.gitignore rename to core-java-modules/core-java-arrays/.gitignore diff --git a/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md similarity index 76% rename from core-java-arrays/README.md rename to core-java-modules/core-java-arrays/README.md index 56110585ac..b5f71cc253 100644 --- a/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -13,3 +13,6 @@ - [How to Invert an Array in Java](http://www.baeldung.com/java-invert-array) - [Array Operations in Java](http://www.baeldung.com/java-common-array-operations) - [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) +- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays) +- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array) +- [Converting Between Stream and Array in Java](https://www.baeldung.com/java-stream-to-array) diff --git a/core-java-arrays/pom.xml b/core-java-modules/core-java-arrays/pom.xml similarity index 99% rename from core-java-arrays/pom.xml rename to core-java-modules/core-java-arrays/pom.xml index d2d0453e87..23db608abc 100644 --- a/core-java-arrays/pom.xml +++ b/core-java-modules/core-java-arrays/pom.xml @@ -4,14 +4,14 @@ com.baeldung core-java-arrays 0.1.0-SNAPSHOT - jar core-java-arrays + jar com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java @@ -389,8 +389,7 @@ - 3.8.1 - 1.16.12 + 3.9 1.19 1.19 diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/AddElementToEndOfArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/AddElementToEndOfArray.java new file mode 100644 index 0000000000..dcd61cdfa7 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/AddElementToEndOfArray.java @@ -0,0 +1,34 @@ +package com.baeldung.array; + +import java.util.ArrayList; +import java.util.Arrays; + +public class AddElementToEndOfArray { + + public Integer[] addElementUsingArraysCopyOf(Integer[] srcArray, int elementToAdd) { + Integer[] destArray = Arrays.copyOf(srcArray, srcArray.length + 1); + + destArray[destArray.length - 1] = elementToAdd; + return destArray; + } + + public Integer[] addElementUsingArrayList(Integer[] srcArray, int elementToAdd) { + Integer[] destArray = new Integer[srcArray.length + 1]; + + ArrayList arrayList = new ArrayList<>(Arrays.asList(srcArray)); + arrayList.add(elementToAdd); + + return arrayList.toArray(destArray); + } + + public Integer[] addElementUsingSystemArrayCopy(Integer[] srcArray, int elementToAdd) { + Integer[] destArray = new Integer[srcArray.length + 1]; + + System.arraycopy(srcArray, 0, destArray, 0, srcArray.length); + + destArray[destArray.length - 1] = elementToAdd; + + return destArray; + } + +} diff --git a/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/Find2ndLargestInArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/Find2ndLargestInArray.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/Find2ndLargestInArray.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/Find2ndLargestInArray.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/FindElementInArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/FindElementInArray.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/FindElementInArray.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/FindElementInArray.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/MultiDimensionalArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/MultiDimensionalArray.java new file mode 100644 index 0000000000..4e01b99a14 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/MultiDimensionalArray.java @@ -0,0 +1,83 @@ +package com.baeldung.array; + +import java.util.Arrays; +import java.util.Scanner; + +public class MultiDimensionalArray { + + int[][] shortHandFormInitialization() { + int[][] multiDimensionalArray = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + return multiDimensionalArray; + } + + int[][] declarationAndThenInitialization() { + int[][] multiDimensionalArray = new int[3][]; + multiDimensionalArray[0] = new int[] { 1, 2 }; + multiDimensionalArray[1] = new int[] { 3, 4, 5 }; + multiDimensionalArray[2] = new int[] { 6, 7, 8, 9 }; + return multiDimensionalArray; + } + + int[][] declarationAndThenInitializationUsingUserInputs() { + int[][] multiDimensionalArray = new int[3][]; + multiDimensionalArray[0] = new int[2]; + multiDimensionalArray[1] = new int[3]; + multiDimensionalArray[2] = new int[4]; + initializeElements(multiDimensionalArray); + return multiDimensionalArray; + } + + void initializeElements(int[][] multiDimensionalArray) { + Scanner sc = new Scanner(System.in); + for (int outer = 0; outer < multiDimensionalArray.length; outer++) { + for (int inner = 0; inner < multiDimensionalArray[outer].length; inner++) { + multiDimensionalArray[outer][inner] = sc.nextInt(); + } + } + } + + void initialize2DArray(int[][] multiDimensionalArray) { + for (int[] array : multiDimensionalArray) { + Arrays.fill(array, 7); + } + } + + void printElements(int[][] multiDimensionalArray) { + for (int index = 0; index < multiDimensionalArray.length; index++) { + System.out.println(Arrays.toString(multiDimensionalArray[index])); + } + } + + int[] getElementAtGivenIndex(int[][] multiDimensionalArray, int index) { + return multiDimensionalArray[index]; + } + + int[] findLengthOfElements(int[][] multiDimensionalArray) { + int[] arrayOfLengths = new int[multiDimensionalArray.length]; + for (int i = 0; i < multiDimensionalArray.length; i++) { + arrayOfLengths[i] = multiDimensionalArray[i].length; + } + return arrayOfLengths; + } + + Integer[] findLengthOfElements(Integer[][] multiDimensionalArray) { + return Arrays.stream(multiDimensionalArray) + .map(array -> array.length) + .toArray(Integer[]::new); + } + + int[][] copy2DArray(int[][] arrayOfArrays) { + int[][] copied2DArray = new int[arrayOfArrays.length][]; + for (int i = 0; i < arrayOfArrays.length; i++) { + int[] array = arrayOfArrays[i]; + copied2DArray[i] = Arrays.copyOf(array, array.length); + } + return copied2DArray; + } + + Integer[][] copy2DArray(Integer[][] arrayOfArrays) { + return Arrays.stream(arrayOfArrays) + .map(array -> Arrays.copyOf(array, array.length)) + .toArray(Integer[][]::new); + } +} diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java new file mode 100644 index 0000000000..62a1a0ee58 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java @@ -0,0 +1,27 @@ +package com.baeldung.array; + +import org.apache.commons.lang3.ArrayUtils; + +public class RemoveElementFromAnArray { + + public int[] removeAnElementWithAGivenIndex(int[] array, int index) { + return ArrayUtils.remove(array, index); + } + + public int[] removeAllElementsWithGivenIndices(int[] array, int... indicies) { + return ArrayUtils.removeAll(array, indicies); + } + + public int[] removeFirstOccurrenceOfGivenElement(int[] array, int element) { + return ArrayUtils.removeElement(array, element); + } + + public int[] removeAllGivenElements(int[] array, int... elements) { + return ArrayUtils.removeElements(array, elements); + } + + public int[] removeAllOccurrencesOfAGivenElement(int[] array, int element) { + return ArrayUtils.removeAllOccurences(array, element); + } + +} diff --git a/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java new file mode 100644 index 0000000000..b831e436a5 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java @@ -0,0 +1,44 @@ +package com.baeldung.array.conversions; + +import java.nio.ByteBuffer; + +public class FloatToByteArray { + + /** + * convert float into byte array using Float API floatToIntBits + * @param value + * @return byte[] + */ + public static byte[] floatToByteArray(float value) { + int intBits = Float.floatToIntBits(value); + return new byte[] {(byte) (intBits >> 24), (byte) (intBits >> 16), (byte) (intBits >> 8), (byte) (intBits) }; + } + + /** + * convert byte array into float using Float API intBitsToFloat + * @param bytes + * @return float + */ + public static float byteArrayToFloat(byte[] bytes) { + int intBits = bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF); + return Float.intBitsToFloat(intBits); + } + + /** + * convert float into byte array using ByteBuffer + * @param value + * @return byte[] + */ + public static byte[] floatToByteArrayWithByteBuffer(float value) { + return ByteBuffer.allocate(4).putFloat(value).array(); + } + + /** + * convert byte array into float using ByteBuffer + * @param bytes + * @return float + */ + public static float byteArrayToFloatWithByteBuffer(byte[] bytes) { + return ByteBuffer.wrap(bytes).getFloat(); + } +} diff --git a/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java diff --git a/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java similarity index 100% rename from core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java diff --git a/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java similarity index 78% rename from core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java rename to core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java index 757a8f8ec1..a7592574d9 100644 --- a/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java @@ -7,6 +7,14 @@ public class Employee implements Serializable { private int id; private String name; + public Employee() { + } + + public Employee(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { return id; } diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java new file mode 100644 index 0000000000..ac54aea402 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java @@ -0,0 +1,44 @@ +package com.baeldung.arrays; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; + +public class ParallelPrefixBenchmark { + private static final int ARRAY_SIZE = 200_000_000; + + @State(Scope.Benchmark) + public static class BigArray { + + int[] data; + + @Setup(Level.Iteration) + public void prepare() { + data = new int[ARRAY_SIZE]; + for(int j = 0; j< ARRAY_SIZE; j++) { + data[j] = 1; + } + } + + @TearDown(Level.Iteration) + public void destroy() { + data = null; + } + + } + + @Benchmark + public void largeArrayLoopSum(BigArray bigArray, Blackhole blackhole) { + for (int i = 0; i < ARRAY_SIZE - 1; i++) { + bigArray.data[i + 1] += bigArray.data[i]; + } + blackhole.consume(bigArray.data); + } + + @Benchmark + public void largeArrayParallelPrefixSum(BigArray bigArray, Blackhole blackhole) { + Arrays.parallelPrefix(bigArray.data, (left, right) -> left + right); + blackhole.consume(bigArray.data); + } +} diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java new file mode 100644 index 0000000000..f6f1f954f6 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.array; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertArrayEquals; + +public class AddElementToEndOfArrayUnitTest { + + AddElementToEndOfArray addElementToEndOfArray; + + @Before + public void init() { + addElementToEndOfArray = new AddElementToEndOfArray(); + } + + @Test + public void givenSourceArrayAndElement_whenAddElementUsingArraysCopyIsInvoked_thenNewElementMustBeAdded() { + Integer[] sourceArray = {1, 2, 3, 4}; + int elementToAdd = 5; + + Integer[] destArray = addElementToEndOfArray.addElementUsingArraysCopyOf(sourceArray, elementToAdd); + + Integer[] expectedArray = {1, 2, 3, 4, 5}; + assertArrayEquals(expectedArray, destArray); + } + + @Test + public void givenSourceArrayAndElement_whenAddElementUsingArrayListIsInvoked_thenNewElementMustBeAdded() { + Integer[] sourceArray = {1, 2, 3, 4}; + int elementToAdd = 5; + + Integer[] destArray = addElementToEndOfArray.addElementUsingArrayList(sourceArray, elementToAdd); + + Integer[] expectedArray = {1, 2, 3, 4, 5}; + assertArrayEquals(expectedArray, destArray); + } + + @Test + public void givenSourceArrayAndElement_whenAddElementUsingSystemArrayCopyIsInvoked_thenNewElementMustBeAdded() { + Integer[] sourceArray = {1, 2, 3, 4}; + int elementToAdd = 5; + + Integer[] destArray = addElementToEndOfArray.addElementUsingSystemArrayCopy(sourceArray, elementToAdd); + + Integer[] expectedArray = {1, 2, 3, 4, 5}; + assertArrayEquals(expectedArray, destArray); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/array/Find2ndLargestInArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/Find2ndLargestInArrayUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/Find2ndLargestInArrayUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/Find2ndLargestInArrayUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/array/FindElementInArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/FindElementInArrayUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/FindElementInArrayUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/FindElementInArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java new file mode 100644 index 0000000000..8980eaa9dc --- /dev/null +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java @@ -0,0 +1,86 @@ +package com.baeldung.array; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; + +import org.junit.Test; + +public class MultiDimensionalArrayUnitTest { + + private MultiDimensionalArray obj = new MultiDimensionalArray(); + + @Test + public void whenInitializedUsingShortHandForm_thenCorrect() { + assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.shortHandFormInitialization()); + } + + @Test + public void whenInitializedWithDeclarationAndThenInitalization_thenCorrect() { + assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.declarationAndThenInitialization()); + } + + @Test + public void whenInitializedWithDeclarationAndThenInitalizationUsingUserInputs_thenCorrect() { + InputStream is = new ByteArrayInputStream("1 2 3 4 5 6 7 8 9".getBytes()); + System.setIn(is); + assertArrayEquals(new int[][] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }, obj.declarationAndThenInitializationUsingUserInputs()); + System.setIn(System.in); + } + + @Test + public void givenMultiDimensionalArrayAndAnIndex_thenReturnArrayAtGivenIndex() { + int[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + assertArrayEquals(new int[] { 1, 2 }, obj.getElementAtGivenIndex(multiDimensionalArr, 0)); + assertArrayEquals(new int[] { 3, 4, 5 }, obj.getElementAtGivenIndex(multiDimensionalArr, 1)); + assertArrayEquals(new int[] { 6, 7, 8, 9 }, obj.getElementAtGivenIndex(multiDimensionalArr, 2)); + } + + @Test + public void givenMultiDimensionalArray_whenUsingArraysAPI_thenVerifyPrintedElements() { + int[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + obj.printElements(multiDimensionalArr); + assertEquals("[1, 2][3, 4, 5][6, 7, 8, 9]", outContent.toString().replace("\r", "").replace("\n", "")); + System.setOut(System.out); + } + + @Test + public void givenMultiDimensionalArray_whenUsingArraysFill_thenVerifyInitialize2DArray() { + int[][] multiDimensionalArr = new int[3][]; + multiDimensionalArr[0] = new int[2]; + multiDimensionalArr[1] = new int[3]; + multiDimensionalArr[2] = new int[4]; + obj.initialize2DArray(multiDimensionalArr); + assertArrayEquals(new int[][] {{7,7}, {7,7,7}, {7,7,7,7}}, multiDimensionalArr); + } + + @Test + public void givenMultiDimensionalArray_whenUsingIteration_thenVerifyFindLengthOfElements() { + int[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + assertArrayEquals(new int[]{2,3,4}, obj.findLengthOfElements(multiDimensionalArr)); + } + + @Test + public void givenMultiDimensionalArray_whenUsingArraysStream_thenVerifyFindLengthOfElements() { + Integer[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + assertArrayEquals(new Integer[]{2,3,4}, obj.findLengthOfElements(multiDimensionalArr)); + } + + @Test + public void givenMultiDimensionalArray_whenUsingArraysCopyOf_thenVerifyCopy2DArray() { + int[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + assertArrayEquals(multiDimensionalArr, obj.copy2DArray(multiDimensionalArr)); + } + + @Test + public void givenMultiDimensionalArray_whenUsingArraysStream_thenVerifyCopy2DArray() { + Integer[][] multiDimensionalArr = { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } }; + assertArrayEquals(multiDimensionalArr, obj.copy2DArray(multiDimensionalArr)); + } +} diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java new file mode 100644 index 0000000000..ea52cd17d9 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java @@ -0,0 +1,85 @@ +package com.baeldung.array; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.jupiter.api.Test; + +class RemoveElementFromAnArrayUnitTest { + + private final RemoveElementFromAnArray sut = new RemoveElementFromAnArray(); + private final int[] inputArray = new int[] { 40, 10, 20, 30, 40, 50 }; + + @Test + void testRemoveAnElementWithAGivenIndex() { + int index = 2; + int[] modifiedArray = sut.removeAnElementWithAGivenIndex(inputArray, index); + + assertFalse(ArrayUtils.contains(modifiedArray, inputArray[index])); + } + + @Test + void testRemoveAllElementsWithGivenIndices() { + int first = 0; + int last = inputArray.length - 1; + int[] modifiedArray = sut.removeAllElementsWithGivenIndices(inputArray, first, last); + + assertFalse(ArrayUtils.contains(modifiedArray, inputArray[first]) && ArrayUtils.contains(modifiedArray, inputArray[last])); + } + + @Test + void testRemoveElement_WhenArrayIsNull_ThrowsIndexOutOfBoundEx() { + int index = 2; + + assertThrows(IndexOutOfBoundsException.class, () -> { + sut.removeAnElementWithAGivenIndex(null, index); + }); + + assertThrows(IndexOutOfBoundsException.class, () -> { + sut.removeAllElementsWithGivenIndices(null, index); + }); + } + + @Test + void testRemoveFirstOccurrenceOfGivenElement() { + int element = 40; + int[] modifiedArray = sut.removeFirstOccurrenceOfGivenElement(inputArray, element); + + int indexInInputArray = ArrayUtils.indexOf(inputArray, element); + int indexInModifiedArray = ArrayUtils.indexOf(modifiedArray, element); + assertFalse(indexInInputArray == indexInModifiedArray); + } + + @Test + void testRemoveAllGivenElements() { + int duplicateElement = 40; + int[] elements = new int[] { duplicateElement, 10, 50 }; + int[] modifiedArray = sut.removeAllGivenElements(inputArray, elements); + + assertTrue(ArrayUtils.contains(modifiedArray, duplicateElement)); + assertFalse(ArrayUtils.contains(modifiedArray, elements[1])); + assertFalse(ArrayUtils.contains(modifiedArray, elements[2])); + } + + @Test + void testRemoveAllOccurrencesOfAGivenElement() { + int element = 40; + int[] modifiedArray = sut.removeAllOccurrencesOfAGivenElement(inputArray, element); + + assertFalse(ArrayUtils.contains(modifiedArray, element)); + } + + @Test + void testRemoveElement_WhenArrayIsNull_ReturnsNull() { + int element = 20; + + assertEquals(null, sut.removeFirstOccurrenceOfGivenElement(null, element)); + assertEquals(null, sut.removeAllGivenElements(null, element)); + assertEquals(null, sut.removeAllOccurrencesOfAGivenElement(null, element)); + + } + +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java new file mode 100644 index 0000000000..a2cd273f21 --- /dev/null +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.array.conversions; + +import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloat; +import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloatWithByteBuffer; +import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArray; +import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArrayWithByteBuffer; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class FloatToByteArrayUnitTest { + + @Test + public void givenAFloat_thenConvertToByteArray() { + assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArray(1.1f)); + } + + @Test + public void givenAByteArray_thenConvertToFloat() { + assertEquals(1.1f, byteArrayToFloat(new byte[] { 63, -116, -52, -51}), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArrayUsingByteBuffer() { + assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArrayWithByteBuffer(1.1f)); + } + + @Test + public void givenAByteArray_thenConvertToFloatUsingByteBuffer() { + assertEquals(1.1f, byteArrayToFloatWithByteBuffer(new byte[] { 63, -116, -52, -51}), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArray_thenConvertToFloat() { + float floatToConvert = 200.12f; + byte[] byteArray = floatToByteArray(floatToConvert); + assertEquals(200.12f, byteArrayToFloat(byteArray), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArrayWithByteBuffer_thenConvertToFloatWithByteBuffer() { + float floatToConvert = 30100.42f; + byte[] byteArray = floatToByteArrayWithByteBuffer(floatToConvert); + assertEquals(30100.42f, byteArrayToFloatWithByteBuffer(byteArray), 0); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java similarity index 100% rename from core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java diff --git a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java similarity index 73% rename from core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java rename to core-java-modules/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java index 9e6d3d6131..b6801612b9 100644 --- a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java @@ -1,5 +1,7 @@ package com.baeldung.arrays; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import org.junit.Before; @@ -9,6 +11,7 @@ import org.junit.rules.ExpectedException; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.stream.Stream; public class ArraysUnitTest { @@ -150,4 +153,52 @@ public class ArraysUnitTest { exception.expect(UnsupportedOperationException.class); rets.add("the"); } + + @Test + public void givenIntArray_whenPrefixAdd_thenAllAccumulated() { + int[] arri = new int[] { 1, 2, 3, 4}; + Arrays.parallelPrefix(arri, (left, right) -> left + right); + assertThat(arri, is(new int[] { 1, 3, 6, 10})); + } + + @Test + public void givenStringArray_whenPrefixConcat_thenAllMerged() { + String[] arrs = new String[] { "1", "2", "3" }; + Arrays.parallelPrefix(arrs, (left, right) -> left + right); + assertThat(arrs, is(new String[] { "1", "12", "123" })); + } + + @Test + public void whenPrefixAddWithRange_thenRangeAdded() { + int[] arri = new int[] { 1, 2, 3, 4, 5 }; + Arrays.parallelPrefix(arri, 1, 4, (left, right) -> left + right); + assertThat(arri, is(new int[] { 1, 2, 5, 9, 5 })); + } + + @Test + public void whenPrefixNonAssociative_thenError() { + boolean consistent = true; + Random r = new Random(); + for (int k = 0; k < 100_000; k++) { + int[] arrA = r.ints(100, 1, 5).toArray(); + int[] arrB = Arrays.copyOf(arrA, arrA.length); + + Arrays.parallelPrefix(arrA, this::nonassociativeFunc); + + for (int i = 1; i < arrB.length; i++) { + arrB[i] = nonassociativeFunc(arrB[i - 1], arrB[i]); + } + consistent = Arrays.equals(arrA, arrB); + if(!consistent) break; + } + assertFalse(consistent); + } + + /** + * non-associative int binary operator + */ + private int nonassociativeFunc(int left, int right) { + return left + right*left; + } + } diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java new file mode 100644 index 0000000000..59035738fe --- /dev/null +++ b/core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java @@ -0,0 +1,90 @@ +package com.baeldung.sort; + +import com.baeldung.arraycopy.model.Employee; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertArrayEquals; + +public class ArraySortUnitTest { + private Employee[] employees; + private int[] numbers; + private String[] strings; + + private Employee john = new Employee(6, "John"); + private Employee mary = new Employee(3, "Mary"); + private Employee david = new Employee(4, "David"); + + @Before + public void setup() { + createEmployeesArray(); + createNumbersArray(); + createStringArray(); + } + + private void createEmployeesArray() { + employees = new Employee[]{john, mary, david}; + } + + private void createNumbersArray() { + numbers = new int[]{-8, 7, 5, 9, 10, -2, 3}; + } + + private void createStringArray() { + strings = new String[]{"learning", "java", "with", "baeldung"}; + } + + @Test + public void givenIntArray_whenSortingAscending_thenCorrectlySorted() { + Arrays.sort(numbers); + + assertArrayEquals(new int[]{-8, -2, 3, 5, 7, 9, 10}, numbers); + } + + @Test + public void givenIntArray_whenSortingDescending_thenCorrectlySorted() { + numbers = IntStream.of(numbers).boxed().sorted(Comparator.reverseOrder()).mapToInt(i -> i).toArray(); + + assertArrayEquals(new int[]{10, 9, 7, 5, 3, -2, -8}, numbers); + } + + @Test + public void givenStringArray_whenSortingAscending_thenCorrectlySorted() { + Arrays.sort(strings); + + assertArrayEquals(new String[]{"baeldung", "java", "learning", "with"}, strings); + } + + @Test + public void givenStringArray_whenSortingDescending_thenCorrectlySorted() { + Arrays.sort(strings, Comparator.reverseOrder()); + + assertArrayEquals(new String[]{"with", "learning", "java", "baeldung"}, strings); + } + + @Test + public void givenObjectArray_whenSortingAscending_thenCorrectlySorted() { + Arrays.sort(employees, Comparator.comparing(Employee::getName)); + + assertArrayEquals(new Employee[]{david, john, mary}, employees); + } + + @Test + public void givenObjectArray_whenSortingDescending_thenCorrectlySorted() { + Arrays.sort(employees, Comparator.comparing(Employee::getName).reversed()); + + assertArrayEquals(new Employee[]{mary, john, david}, employees); + } + + @Test + public void givenObjectArray_whenSortingMultipleAttributesAscending_thenCorrectlySorted() { + Arrays.sort(employees, Comparator.comparing(Employee::getName).thenComparing(Employee::getId)); + + assertArrayEquals(new Employee[]{david, john, mary}, employees); + } + +} diff --git a/core-java-modules/core-java-collections-array-list/README.md b/core-java-modules/core-java-collections-array-list/README.md new file mode 100644 index 0000000000..3d1cdd5085 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/README.md @@ -0,0 +1,10 @@ +========= + +## Core Java Collections Array List Cookbooks and Examples + +### Relevant Articles: +- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) +- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist) +- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list) +- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) +- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) \ No newline at end of file diff --git a/core-java-modules/core-java-collections-array-list/pom.xml b/core-java-modules/core-java-collections-array-list/pom.xml new file mode 100644 index 0000000000..95a5f3ea36 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + core-java-collections-array-list + 0.1.0-SNAPSHOT + core-java-collections-array-list + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + 4.1 + 3.8.1 + 3.11.1 + + diff --git a/core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/Flower.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/Flower.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/list/Flower.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/Flower.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java similarity index 51% rename from core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java rename to core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java index 72045d6761..e11f8e8ba0 100644 --- a/core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java +++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java @@ -6,30 +6,29 @@ public class ArrayListOfArrayList { public static void main(String args[]) { - int vertex = 5; - ArrayList> graph = new ArrayList<>(vertex); + int vertexCount = 3; + ArrayList> graph = new ArrayList<>(vertexCount); //Initializing each element of ArrayList with ArrayList - for(int i=0; i< vertex; i++) { + for(int i = 0; i< vertexCount; i++) { graph.add(new ArrayList()); } //We can add any number of columns to each row graph.get(0).add(1); - graph.get(0).add(5); - graph.get(1).add(0); graph.get(1).add(2); + graph.get(2).add(0); + graph.get(1).add(0); graph.get(2).add(1); - graph.get(2).add(3); - graph.get(3).add(2); - graph.get(3).add(4); - graph.get(4).add(3); - graph.get(4).add(5); + graph.get(0).add(2); - //Printing all the edges - for(int i=0; i > > space = new ArrayList<>(x_axis_length); //Initializing each element of ArrayList with ArrayList< ArrayList > - for(int i=0; i< x_axis_length; i++) { + for(int i = 0; i < x_axis_length; i++) { space.add(new ArrayList< ArrayList >(y_axis_length)); - for(int j =0; j< y_axis_length; j++) { + for(int j = 0; j < y_axis_length; j++) { space.get(i).add(new ArrayList(z_axis_length)); } } //Set Red color for points (0,0,0) and (0,0,1) - space.get(0).get(0).add("Red"); - space.get(0).get(0).add("Red"); + space.get(0).get(0).add(0,"Red"); + space.get(0).get(0).add(1,"Red"); //Set Blue color for points (0,1,0) and (0,1,1) - space.get(0).get(1).add("Blue"); - space.get(0).get(1).add("Blue"); + space.get(0).get(1).add(0,"Blue"); + space.get(0).get(1).add(1,"Blue"); //Set Green color for points (1,0,0) and (1,0,1) - space.get(1).get(0).add("Green"); - space.get(1).get(0).add("Green"); + space.get(1).get(0).add(0,"Green"); + space.get(1).get(0).add(1,"Green"); //Set Yellow color for points (1,1,0) and (1,1,1) - space.get(1).get(1).add("Yellow"); - space.get(1).get(1).add("Yellow"); + space.get(1).get(1).add(0,"Yellow"); + space.get(1).get(1).add(1,"Yellow"); //Printing colors for all the points - for(int i=0; i + 4.0.0 + core-java-collections-list-2 + 0.1.0-SNAPSHOT + core-java-collections-list-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + net.sf.trove4j + trove4j + ${trove4j.version} + + + it.unimi.dsi + fastutil + ${fastutil.version} + + + colt + colt + ${colt.version} + + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + + + + + 4.1 + 3.8.1 + 3.11.1 + 3.0.2 + 8.1.0 + 1.2.0 + + diff --git a/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java new file mode 100644 index 0000000000..936e89893c --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/allequalelements/VerifyAllEqualListElements.java @@ -0,0 +1,55 @@ +package com.baeldung.allequalelements; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import org.apache.commons.collections4.IterableUtils; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; + +public class VerifyAllEqualListElements { + + public boolean verifyAllEqualUsingALoop(List list) { + for (String s : list) { + if (!s.equals(list.get(0))) + return false; + } + return true; + } + + public boolean verifyAllEqualUsingHashSet(List list) { + return new HashSet(list).size() <= 1; + } + + public boolean verifyAllEqualUsingFrequency(List list) { + return list.isEmpty() || Collections.frequency(list, list.get(0)) == list.size(); + } + + public boolean verifyAllEqualUsingStream(List list) { + return list.stream() + .distinct() + .count() <= 1; + } + + public boolean verifyAllEqualAnotherUsingStream(List list) { + return list.isEmpty() || list.stream() + .allMatch(list.get(0)::equals); + } + + public boolean verifyAllEqualUsingGuava(List list) { + return Iterables.all(list, new Predicate() { + public boolean apply(String s) { + return s.equals(list.get(0)); + } + }); + } + + public boolean verifyAllEqualUsingApacheCommon(List list) { + return IterableUtils.matchesAll(list, new org.apache.commons.collections4.Predicate() { + public boolean evaluate(String s) { + return s.equals(list.get(0)); + } + }); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/collection/filtering/Employee.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/collection/filtering/Employee.java new file mode 100644 index 0000000000..2aa267b4dc --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/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; + } + +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/WaysToIterate.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/java/list/WaysToIterate.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/list/WaysToIterate.java rename to core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/java/list/WaysToIterate.java diff --git a/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java new file mode 100644 index 0000000000..01372763e9 --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -0,0 +1,52 @@ +package com.baeldung.list.primitive; + +import com.google.common.primitives.ImmutableIntArray; +import com.google.common.primitives.Ints; +import gnu.trove.list.array.TIntArrayList; +import it.unimi.dsi.fastutil.ints.IntArrayList; + +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.function.IntPredicate; +import java.util.stream.IntStream; + +public class PrimitiveCollections { + + public static void main(String[] args) { + + int[] primitives = new int[] {5, 10, 0, 2, -8}; + + guavaPrimitives(primitives); + + intStream(primitives); + + TIntArrayList tList = new TIntArrayList(primitives); + + cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(primitives); + + IntArrayList fastUtilList = new IntArrayList(primitives); + + System.out.println(tList); + + System.out.println(coltList); + + System.out.println(fastUtilList); + } + + private static void intStream(int[] primitives) { + + IntStream stream = IntStream.of(5, 10, 0, 2, -8); + + IntStream newStream = IntStream.of(primitives); + + OptionalDouble average = stream.filter(i -> i > 0).average(); + } + + + private static void guavaPrimitives(int[] primitives) { + + ImmutableIntArray immutableIntArray = ImmutableIntArray.builder().addAll(primitives).build(); + System.out.println(immutableIntArray); + } +} diff --git a/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-modules/core-java-collections-list-2/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java new file mode 100644 index 0000000000..bd37e5e74e --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/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 addTroveIntList() { + 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 getTroveIntList() { + 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 containsTroveIntList() { + 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(); + } +} diff --git a/core-java-modules/core-java-collections-list-2/src/main/resources/logback.xml b/core-java-modules/core-java-collections-list-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections-list-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/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java new file mode 100644 index 0000000000..698725591c --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/allequalelements/VerifyAllEqualListElementsUnitTest.java @@ -0,0 +1,172 @@ +package com.baeldung.allequalelements; + +import org.junit.Test; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class VerifyAllEqualListElementsUnitTest { + + private static List notAllEqualList = new ArrayList<>(); + + private static List emptyList = new ArrayList<>(); + + private static List allEqualList = new ArrayList<>(); + + static { + notAllEqualList = Arrays.asList("Jack", "James", "Sam", "James"); + emptyList = Arrays.asList(); + allEqualList = Arrays.asList("Jack", "Jack", "Jack", "Jack"); + } + + private static VerifyAllEqualListElements verifyAllEqualListElements = new VerifyAllEqualListElements(); + + @Test + public void givenNotAllEqualList_whenUsingALoop_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingALoop(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingALoop_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingALoop(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingALoop_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingALoop(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingHashSet_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingHashSet(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingHashSet_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingHashSet(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingHashSet_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingHashSet(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingFrequency_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingFrequency(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingFrequency_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingFrequency(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingFrequency_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingFrequency(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingStream_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingStream(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingStream_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingStream(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingStream_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingStream(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingAnotherStream_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualAnotherUsingStream(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingAnotherStream_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualAnotherUsingStream(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingAnotherStream_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualAnotherUsingStream(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingGuava_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingGuava(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingGuava_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingGuava(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingGuava_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingGuava(allEqualList); + + assertTrue(allEqual); + } + + @Test + public void givenNotAllEqualList_whenUsingApacheCommon_thenReturnFalse() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingApacheCommon(notAllEqualList); + + assertFalse(allEqual); + } + + @Test + public void givenEmptyList_whenUsingApacheCommon_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingApacheCommon(emptyList); + + assertTrue(allEqual); + } + + @Test + public void givenAllEqualList_whenUsingApacheCommon_thenReturnTrue() { + boolean allEqual = verifyAllEqualListElements.verifyAllEqualUsingApacheCommon(allEqualList); + + assertTrue(allEqual); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java diff --git a/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java new file mode 100644 index 0000000000..cbc7136192 --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.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 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)); + } + + 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())); + } + +} diff --git a/core-java-collections/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java diff --git a/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListJUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListJUnitTest.java new file mode 100644 index 0000000000..f9c9d3fda8 --- /dev/null +++ b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListJUnitTest.java @@ -0,0 +1,47 @@ +package org.baeldung.java.lists; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.HashSet; + +import java.util.stream.Collectors; + +public class ListJUnitTest { + + private final List list1 = Arrays.asList("1", "2", "3", "4"); + private final List list2 = Arrays.asList("1", "2", "3", "4"); + private final List list3 = Arrays.asList("1", "2", "4", "3"); + + @Test + public void whenTestingForEquality_ShouldBeEqual() throws Exception { + Assert.assertEquals(list1, list2); + Assert.assertNotSame(list1, list2); + Assert.assertNotEquals(list1, list3); + } + + @Test + public void whenIntersection_ShouldReturnCommonElements() throws Exception { + List list = Arrays.asList("red", "blue", "blue", "green", "red"); + List otherList = Arrays.asList("red", "green", "green", "yellow"); + + Set commonElements = new HashSet(Arrays.asList("red", "green")); + + Set result = list.stream() + .distinct() + .filter(otherList::contains) + .collect(Collectors.toSet()); + + Assert.assertEquals(commonElements, result); + + Set inverseResult = otherList.stream() + .distinct() + .filter(list::contains) + .collect(Collectors.toSet()); + + Assert.assertEquals(commonElements, inverseResult); + } +} diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/README.md b/core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/README.md similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/lists/README.md rename to core-java-modules/core-java-collections-list-2/src/test/java/org/baeldung/java/lists/README.md diff --git a/core-java-modules/core-java-collections-list/README.md b/core-java-modules/core-java-collections-list/README.md new file mode 100644 index 0000000000..4bc1c5fb57 --- /dev/null +++ b/core-java-modules/core-java-collections-list/README.md @@ -0,0 +1,16 @@ +========= + +## Core Java Collections List Cookbooks and Examples + +### Relevant Articles: +- [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) +- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards) +- [Remove the First Element from a List](http://www.baeldung.com/java-remove-first-element-from-list) +- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java) +- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) +- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max) +- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list) +- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list) \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/pom.xml b/core-java-modules/core-java-collections-list/pom.xml new file mode 100644 index 0000000000..581505dc1e --- /dev/null +++ b/core-java-modules/core-java-collections-list/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + core-java-collections-list + 0.1.0-SNAPSHOT + core-java-collections-list + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + 4.1 + 3.8.1 + 3.11.1 + 3.0.2 + + diff --git a/core-java-collections/src/main/java/com/baeldung/findanelement/Customer.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/findanelement/Customer.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/findanelement/Customer.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/findanelement/Customer.java diff --git a/core-java-collections/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/CopyListService.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/CopyListService.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/list/CopyListService.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/CopyListService.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/CustomList.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/CustomList.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/list/CustomList.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/CustomList.java diff --git a/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/Flower.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/Flower.java new file mode 100644 index 0000000000..eb897ea72f --- /dev/null +++ b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/Flower.java @@ -0,0 +1,28 @@ +package com.baeldung.java.list; + +public class Flower { + + private String name; + private int petals; + + public Flower(String name, int petals) { + this.name = name; + this.petals = petals; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPetals() { + return petals; + } + + public void setPetals(int petals) { + this.petals = petals; + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/ReverseIterator.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/ReverseIterator.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/list/ReverseIterator.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java/list/ReverseIterator.java diff --git a/core-java-collections/src/main/java/com/baeldung/java_8_features/Car.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Car.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java_8_features/Car.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Car.java diff --git a/core-java-collections/src/main/java/com/baeldung/java_8_features/Person.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Person.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java_8_features/Person.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Person.java diff --git a/core-java-8/src/main/java/com/baeldung/list/Flower.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/Flower.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/list/Flower.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/Flower.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Pen.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pen.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Pen.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pen.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Pencil.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pencil.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Pencil.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pencil.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Rubber.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Rubber.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Rubber.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Rubber.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Stationery.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Stationery.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Stationery.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Stationery.java diff --git a/core-java-collections/src/main/java/com/baeldung/list/removeall/RemoveAll.java b/core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/removeall/RemoveAll.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/list/removeall/RemoveAll.java rename to core-java-modules/core-java-collections-list/src/main/java/com/baeldung/list/removeall/RemoveAll.java diff --git a/core-java-modules/core-java-collections-list/src/main/resources/logback.xml b/core-java-modules/core-java-collections-list/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections-list/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-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/collection/CollectionsEmpty.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/CollectionsEmpty.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/collection/CollectionsEmpty.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/collection/CollectionsEmpty.java diff --git a/core-java-collections/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/CustomListUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/CustomListUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/list/CustomListUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/CustomListUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/AddElementsUnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/AddElementsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java index 6ae7c40f4d..4f5ba0f82f 100644 --- a/core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java +++ b/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung; +package org.baeldung; import com.google.common.collect.Lists; import org.junit.Test; diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java b/core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java rename to core-java-modules/core-java-collections-list/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java diff --git a/core-java-modules/core-java-collections-set/README.md b/core-java-modules/core-java-collections-set/README.md new file mode 100644 index 0000000000..618b4e932c --- /dev/null +++ b/core-java-modules/core-java-collections-set/README.md @@ -0,0 +1,13 @@ +========= + +## Core Java Sets Cookbooks and Examples + +### Relevant Articles: +- [Set Operations in Java](http://www.baeldung.com/set-operations-in-java) +- [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset) +- [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset) +- [A Guide to TreeSet in Java](http://www.baeldung.com/java-tree-set) +- [Initializing HashSet at the Time of Construction](http://www.baeldung.com/java-initialize-hashset) +- [Guide to EnumSet](https://www.baeldung.com/java-enumset) +- [Set Operations in Java](https://www.baeldung.com/java-set-operations) +- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets) diff --git a/core-java-modules/core-java-collections-set/pom.xml b/core-java-modules/core-java-collections-set/pom.xml new file mode 100644 index 0000000000..101ed79de0 --- /dev/null +++ b/core-java-modules/core-java-collections-set/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + core-java-collections-set + 0.1.0-SNAPSHOT + core-java-collections-set + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + com.google.guava + guava + ${guava.version} + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + com.google.code.gson + gson + ${gson.version} + + + commons-lang + commons-lang + ${commons-lang.version} + + + + + 4.3 + 27.1-jre + 2.8.5 + + \ No newline at end of file diff --git a/core-java-collections/src/main/java/com/baeldung/enumset/EnumSets.java b/core-java-modules/core-java-collections-set/src/main/java/com/baeldung/enumset/EnumSets.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/enumset/EnumSets.java rename to core-java-modules/core-java-collections-set/src/main/java/com/baeldung/enumset/EnumSets.java diff --git a/core-java-modules/core-java-collections-set/src/main/java/com/baeldung/set/CopySets.java b/core-java-modules/core-java-collections-set/src/main/java/com/baeldung/set/CopySets.java new file mode 100644 index 0000000000..53933e4439 --- /dev/null +++ b/core-java-modules/core-java-collections-set/src/main/java/com/baeldung/set/CopySets.java @@ -0,0 +1,59 @@ +package com.baeldung.set; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang.SerializationUtils; + +import com.google.gson.Gson; + +public class CopySets { + + // Copy Constructor + public static Set copyByConstructor(Set original) { + Set copy = new HashSet<>(original); + return copy; + } + + // Set.addAll + public static Set copyBySetAddAll(Set original) { + Set copy = new HashSet<>(); + copy.addAll(original); + return copy; + } + + // Set.clone + public static Set copyBySetClone(HashSet original) { + Set copy = (Set) original.clone(); + return copy; + } + + // JSON + public static Set copyByJson(Set original) { + Gson gson = new Gson(); + String jsonStr = gson.toJson(original); + Set copy = gson.fromJson(jsonStr, Set.class); + + return copy; + } + + // Apache Commons Lang + public static Set copyByApacheCommonsLang(Set original) { + Set copy = new HashSet<>(); + for (T item : original) { + copy.add((T) SerializationUtils.clone(item)); + } + return copy; + } + + // Collectors.toSet + public static Set copyByCollectorsToSet(Set original) { + Set copy = original.stream() + .collect(Collectors.toSet()); + + return copy; + } + +} diff --git a/core-java-collections/src/test/java/com/baeldung/collection/WhenUsingHashSet.java b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/collection/WhenUsingHashSet.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/collection/WhenUsingHashSet.java rename to core-java-modules/core-java-collections-set/src/test/java/com/baeldung/collection/WhenUsingHashSet.java diff --git a/core-java-collections/src/test/java/com/baeldung/collection/WhenUsingTreeSet.java b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/collection/WhenUsingTreeSet.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/collection/WhenUsingTreeSet.java rename to core-java-modules/core-java-collections-set/src/test/java/com/baeldung/collection/WhenUsingTreeSet.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/set/HashSetInitalizingUnitTest.java b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/java/set/HashSetInitalizingUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/set/HashSetInitalizingUnitTest.java rename to core-java-modules/core-java-collections-set/src/test/java/com/baeldung/java/set/HashSetInitalizingUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/set/SetUnitTest.java b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/java/set/SetUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/set/SetUnitTest.java rename to core-java-modules/core-java-collections-set/src/test/java/com/baeldung/java/set/SetUnitTest.java diff --git a/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java new file mode 100644 index 0000000000..7c25585e49 --- /dev/null +++ b/core-java-modules/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.set; + +import static org.junit.Assert.*; + +import org.apache.commons.collections4.SetUtils; +import org.junit.Test; + +import com.google.common.collect.Sets; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SetOperationsUnitTest { + + private Set setA = setOf(1,2,3,4); + private Set setB = setOf(2,4,6,8); + + private static Set setOf(Integer... values) { + return new HashSet(Arrays.asList(values)); + } + + @Test + public void givenTwoSets_WhenWeRetainAll_ThenWeIntersectThem() { + Set intersectSet = new HashSet<>(setA); + intersectSet.retainAll(setB); + assertEquals(setOf(2,4), intersectSet); + } + + @Test + public void givenTwoSets_WhenWeAddAll_ThenWeUnionThem() { + Set unionSet = new HashSet<>(setA); + unionSet.addAll(setB); + assertEquals(setOf(1,2,3,4,6,8), unionSet); + } + + @Test + public void givenTwoSets_WhenRemoveAll_ThenWeGetTheDifference() { + Set differenceSet = new HashSet<>(setA); + differenceSet.removeAll(setB); + assertEquals(setOf(1,3), differenceSet); + } + + @Test + public void givenTwoStreams_WhenWeFilterThem_ThenWeCanGetTheIntersect() { + Set intersectSet = setA.stream() + .filter(setB::contains) + .collect(Collectors.toSet()); + assertEquals(setOf(2,4), intersectSet); + } + + @Test + public void givenTwoStreams_WhenWeConcatThem_ThenWeGetTheUnion() { + Set unionSet = Stream.concat(setA.stream(), setB.stream()) + .collect(Collectors.toSet()); + assertEquals(setOf(1,2,3,4,6,8), unionSet); + } + + @Test + public void givenTwoStreams_WhenWeFilterThem_ThenWeCanGetTheDifference() { + Set differenceSet = setA.stream() + .filter(val -> !setB.contains(val)) + .collect(Collectors.toSet()); + assertEquals(setOf(1,3), differenceSet); + } + + @Test + public void givenTwoSets_WhenWeUseApacheCommonsIntersect_ThenWeGetTheIntersect() { + Set intersectSet = SetUtils.intersection(setA, setB); + assertEquals(setOf(2,4), intersectSet); + } + + @Test + public void givenTwoSets_WhenWeUseApacheCommonsUnion_ThenWeGetTheUnion() { + Set unionSet = SetUtils.union(setA, setB); + assertEquals(setOf(1,2,3,4,6,8), unionSet); + } + + + @Test + public void givenTwoSets_WhenWeUseGuavaIntersect_ThenWeGetTheIntersect() { + Set intersectSet = Sets.intersection(setA, setB); + assertEquals(setOf(2,4), intersectSet); + } + + @Test + public void givenTwoSets_WhenWeUseGuavaUnion_ThenWeGetTheUnion() { + Set unionSet = Sets.union(setA, setB); + assertEquals(setOf(1,2,3,4,6,8), unionSet); + } +} diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md new file mode 100644 index 0000000000..b34293769d --- /dev/null +++ b/core-java-modules/core-java-collections/README.md @@ -0,0 +1,31 @@ +========= + +## Core Java Collections Cookbooks and Examples + +### Relevant Articles: +- [Java – Combine Multiple Collections](http://www.baeldung.com/java-combine-multiple-collections) +- [Collect a Java Stream to an Immutable Collection](http://www.baeldung.com/java-stream-immutable-collection) +- [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque) +- [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size) +- [How to Filter a Collection in Java](http://www.baeldung.com/java-collection-filtering) +- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) +- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator) +- [Shuffling Collections In Java](http://www.baeldung.com/java-shuffle-collection) +- [An Introduction to Java.util.Hashtable Class](http://www.baeldung.com/java-hash-table) +- [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections) +- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe) +- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall) +- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance) +- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity) +- [Operating on and Removing an Item from Stream](https://www.baeldung.com/java-use-remove-item-stream) +- [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) +- [Removing Elements from Java Collections](https://www.baeldung.com/java-collection-remove-elements) +- [Combining Different Types of Collections in Java](https://www.baeldung.com/java-combine-collections) +- [Sorting in Java](http://www.baeldung.com/java-sorting) +- [Join and Split Arrays and Collections in Java](http://www.baeldung.com/java-join-and-split) +- [A Guide to EnumMap](https://www.baeldung.com/java-enum-map) +- [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) +- [Time Comparison of Arrays.sort(Object[]) and Arrays.sort(int[])](https://www.baeldung.com/arrays-sortobject-vs-sortint) diff --git a/core-java-collections/pom.xml b/core-java-modules/core-java-collections/pom.xml similarity index 93% rename from core-java-collections/pom.xml rename to core-java-modules/core-java-collections/pom.xml index 2201ee8b15..e5b89c3d16 100644 --- a/core-java-collections/pom.xml +++ b/core-java-modules/core-java-collections/pom.xml @@ -1,78 +1,78 @@ - - 4.0.0 - core-java-collections - 0.1.0-SNAPSHOT - jar - core-java-collections - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.apache.commons - commons-collections4 - ${commons-collections4.version} - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - org.eclipse.collections - eclipse-collections - ${eclipse.collections.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - org.openjdk.jmh - jmh-core - ${openjdk.jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${openjdk.jmh.version} - - - org.apache.commons - commons-exec - 1.3 - - - org.projectlombok - lombok - ${lombok.version} - provided - - - - - 1.19 - 1.2.0 - 3.8.1 - 4.1 - 4.01 - 1.7.0 - 3.11.1 - 7.1.0 - 1.16.12 - - + + 4.0.0 + core-java-collections + 0.1.0-SNAPSHOT + core-java-collections + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.eclipse.collections + eclipse-collections + ${eclipse.collections.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.openjdk.jmh + jmh-core + ${openjdk.jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${openjdk.jmh.version} + + + org.apache.commons + commons-exec + ${commons-exec.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + 1.19 + 1.2.0 + 3.8.1 + 4.1 + 4.01 + 1.7.0 + 3.11.1 + 7.1.0 + 1.3 + + diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStack.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStack.java new file mode 100644 index 0000000000..f789a68d90 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStack.java @@ -0,0 +1,37 @@ +package com.baeldung.charstack; + +import java.util.Iterator; +import java.util.LinkedList; + +public class CharStack { + + private LinkedList items; + + public CharStack() { + this.items = new LinkedList(); + } + + public void push(Character item) { + items.push(item); + } + + public Character peek() { + return items.getFirst(); + } + + public Character pop() { + + Iterator iter = items.iterator(); + Character item = iter.next(); + if (item != null) { + iter.remove(); + return item; + } + return null; + } + + public int size() { + return items.size(); + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStackWithArray.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStackWithArray.java new file mode 100644 index 0000000000..ed7fa3f253 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/CharStackWithArray.java @@ -0,0 +1,48 @@ +package com.baeldung.charstack; + +public class CharStackWithArray { + + private char[] elements; + private int size; + + public CharStackWithArray() { + size = 0; + elements = new char[4]; + } + + public int size() { + return size; + } + + public char peek() { + if (size == 0) { + throw new EmptyStackException(); + } + return elements[size - 1]; + } + + public char pop() { + if (size == 0) { + throw new EmptyStackException(); + } + + return elements[--size]; + } + + public void push(char item) { + ensureCapacity(size + 1); + elements[size] = item; + size++; + } + + private void ensureCapacity(int newSize) { + char newBiggerArray[]; + + if (elements.length < newSize) { + newBiggerArray = new char[elements.length * 2]; + System.arraycopy(elements, 0, newBiggerArray, 0, size); + elements = newBiggerArray; + } + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/EmptyStackException.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/EmptyStackException.java new file mode 100644 index 0000000000..f005854e7f --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/charstack/EmptyStackException.java @@ -0,0 +1,9 @@ +package com.baeldung.charstack; + +public class EmptyStackException extends RuntimeException { + + public EmptyStackException() { + super("Stack is empty"); + } + +} diff --git a/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningArrays.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningArrays.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningArrays.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningArrays.java diff --git a/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningLists.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningLists.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningLists.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningLists.java diff --git a/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningMaps.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningMaps.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningMaps.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningMaps.java diff --git a/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningSets.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningSets.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningSets.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/combiningcollections/CombiningSets.java diff --git a/core-java-collections/src/main/java/com/baeldung/hashtable/Word.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/hashtable/Word.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/hashtable/Word.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/hashtable/Word.java diff --git a/core-java/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java similarity index 100% rename from core-java/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java diff --git a/core-java-collections/src/main/java/com/baeldung/iterators/Iterators.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/iterators/Iterators.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/iterators/Iterators.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/iterators/Iterators.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/iterable/IterableSize.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/iterable/IterableSize.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/java/iterable/IterableSize.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/java/iterable/IterableSize.java diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java new file mode 100644 index 0000000000..7debc07911 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java @@ -0,0 +1,27 @@ +package com.baeldung.java.list; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Vector; + +public class VectorExample { + + public static void main(String[] args) { + + Vector vector = new Vector<>(); + vector.add("baeldung"); + vector.add("Vector"); + vector.add("example"); + + Enumeration e = vector.elements(); + while(e.hasMoreElements()){ + System.out.println(e.nextElement()); + } + + Iterator iterator = vector.iterator(); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } + +} diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java new file mode 100644 index 0000000000..1eff522877 --- /dev/null +++ b/core-java-modules/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/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java diff --git a/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java diff --git a/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java similarity index 75% rename from core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java index dddd85007d..331ae8d908 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java @@ -9,7 +9,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 10) public class ArrayListBenchmark { @@ -17,6 +17,7 @@ public class ArrayListBenchmark { public static class MyState { List employeeList = new ArrayList<>(); + Vector employeeVector = new Vector<>(); //LinkedList employeeList = new LinkedList<>(); long iterations = 100000; @@ -29,9 +30,11 @@ public class ArrayListBenchmark { public void setUp() { for (long i = 0; i < iterations; i++) { employeeList.add(new Employee(i, "John")); + employeeVector.add(new Employee(i, "John")); } employeeList.add(employee); + employeeVector.add(employee); employeeIndex = employeeList.indexOf(employee); } } @@ -46,6 +49,11 @@ public class ArrayListBenchmark { return state.employeeList.contains(state.employee); } + @Benchmark + public boolean testContainsVector(ArrayListBenchmark.MyState state) { + return state.employeeVector.contains(state.employee); + } + @Benchmark public int testIndexOf(ArrayListBenchmark.MyState state) { return state.employeeList.indexOf(state.employee); @@ -56,19 +64,24 @@ public class ArrayListBenchmark { return state.employeeList.get(state.employeeIndex); } + @Benchmark + public Employee testVectorGet(ArrayListBenchmark.MyState state) { + return state.employeeVector.get(state.employeeIndex); + } + @Benchmark public boolean testRemove(ArrayListBenchmark.MyState state) { return state.employeeList.remove(state.employee); } -// @Benchmark -// public void testAdd(ArrayListBenchmark.MyState state) { -// state.employeeList.add(new Employee(state.iterations + 1, "John")); -// } + @Benchmark + public void testAdd(ArrayListBenchmark.MyState state) { + state.employeeList.add(new Employee(state.iterations + 1, "John")); + } public static void main(String[] args) throws Exception { Options options = new OptionsBuilder() - .include(ArrayListBenchmark.class.getSimpleName()).threads(1) + .include(ArrayListBenchmark.class.getSimpleName()).threads(3) .forks(1).shouldFailOnError(true) .shouldDoGC(true) .jvmArgs("-server").build(); diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java new file mode 100644 index 0000000000..b93f8e9cc2 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -0,0 +1,51 @@ +package com.baeldung.performance; + +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; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Measurement(batchSize = 100000, iterations = 10) +@Warmup(batchSize = 100000, iterations = 10) +public class ArraySortBenchmark { + + @State(Scope.Thread) + public static class Initialize { + 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 + public Integer[] benchmarkArraysIntegerSort(ArraySortBenchmark.Initialize state) { + Arrays.sort(state.numbers); + return state.numbers; + } + + @Benchmark + 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) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/performance/CollectionsBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/CollectionsBenchmark.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/performance/CollectionsBenchmark.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/CollectionsBenchmark.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/CopyOnWriteBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/CopyOnWriteBenchmark.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/performance/CopyOnWriteBenchmark.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/CopyOnWriteBenchmark.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/Employee.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/Employee.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/performance/Employee.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/Employee.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/HashMapBenchmark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/HashMapBenchmark.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/performance/HashMapBenchmark.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/HashMapBenchmark.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/SetBenchMark.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/SetBenchMark.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/performance/SetBenchMark.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/performance/SetBenchMark.java diff --git a/core-java-modules/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java new file mode 100644 index 0000000000..4fcc211812 --- /dev/null +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java @@ -0,0 +1,48 @@ +package com.baeldung.queueInterface; + +import java.util.AbstractQueue; +import java.util.Iterator; +import java.util.LinkedList; + +public class CustomBaeldungQueue extends AbstractQueue { + + private LinkedList elements; + + public CustomBaeldungQueue() { + this.elements = new LinkedList(); + } + + @Override + public Iterator iterator() { + return elements.iterator(); + } + + @Override + public int size() { + return elements.size(); + } + + @Override + public boolean offer(T t) { + if(t == null) return false; + elements.add(t); + return true; + } + + @Override + public T poll() { + + Iterator iter = elements.iterator(); + T t = iter.next(); + if(t != null){ + iter.remove(); + return t; + } + return null; + } + + @Override + public T peek() { + return elements.getFirst(); + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/removal/CollectionRemoveIf.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/CollectionRemoveIf.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/removal/CollectionRemoveIf.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/CollectionRemoveIf.java diff --git a/core-java-collections/src/main/java/com/baeldung/removal/Iterators.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/Iterators.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/removal/Iterators.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/Iterators.java diff --git a/core-java-collections/src/main/java/com/baeldung/removal/StreamFilterAndCollector.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/StreamFilterAndCollector.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/removal/StreamFilterAndCollector.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/StreamFilterAndCollector.java diff --git a/core-java-collections/src/main/java/com/baeldung/removal/StreamPartitioningBy.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/StreamPartitioningBy.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/removal/StreamPartitioningBy.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/removal/StreamPartitioningBy.java diff --git a/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java similarity index 97% rename from core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java index 1840c125d0..093308a34a 100644 --- a/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java +++ b/core-java-modules/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java @@ -1,18 +1,18 @@ -package com.baeldung.synchronizedcollections.application; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.logging.Logger; - -public class Application { - - private static final Logger LOGGER = Logger.getLogger(Application.class.getName()); - - public static void main(String[] args) throws InterruptedException { - List syncCollection = Collections.synchronizedList(Arrays.asList(1, 2, 3, 4, 5, 6)); - synchronized (syncCollection) { - syncCollection.forEach((e) -> {LOGGER.info(e.toString());}); - } - } -} +package com.baeldung.synchronizedcollections.application; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +public class Application { + + private static final Logger LOGGER = Logger.getLogger(Application.class.getName()); + + public static void main(String[] args) throws InterruptedException { + List syncCollection = Collections.synchronizedList(Arrays.asList(1, 2, 3, 4, 5, 6)); + synchronized (syncCollection) { + syncCollection.forEach((e) -> {LOGGER.info(e.toString());}); + } + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/thread_safe_lifo/DequeBasedSynchronizedStack.java b/core-java-modules/core-java-collections/src/main/java/com/baeldung/thread_safe_lifo/DequeBasedSynchronizedStack.java similarity index 100% rename from core-java-collections/src/main/java/com/baeldung/thread_safe_lifo/DequeBasedSynchronizedStack.java rename to core-java-modules/core-java-collections/src/main/java/com/baeldung/thread_safe_lifo/DequeBasedSynchronizedStack.java diff --git a/core-java-modules/core-java-collections/src/main/resources/logback.xml b/core-java-modules/core-java-collections/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections/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-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java similarity index 95% rename from core-java-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java index 71930eda97..5a76eb5402 100644 --- a/core-java-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/arraydeque/ArrayDequeUnitTest.java @@ -1,50 +1,50 @@ -package com.baeldung.arraydeque; - -import java.util.ArrayDeque; -import java.util.Deque; - -import static org.junit.Assert.*; -import org.junit.Test; - -public class ArrayDequeUnitTest { - - @Test - public void whenOffer_addsAtLast() { - final Deque deque = new ArrayDeque<>(); - - deque.offer("first"); - deque.offer("second"); - - assertEquals("second", deque.getLast()); - } - - @Test - public void whenPoll_removesFirst() { - final Deque deque = new ArrayDeque<>(); - - deque.offer("first"); - deque.offer("second"); - - assertEquals("first", deque.poll()); - } - - @Test - public void whenPush_addsAtFirst() { - final Deque deque = new ArrayDeque<>(); - - deque.push("first"); - deque.push("second"); - - assertEquals("second", deque.getFirst()); - } - - @Test - public void whenPop_removesLast() { - final Deque deque = new ArrayDeque<>(); - - deque.push("first"); - deque.push("second"); - - assertEquals("second", deque.pop()); - } -} +package com.baeldung.arraydeque; + +import java.util.ArrayDeque; +import java.util.Deque; + +import static org.junit.Assert.*; +import org.junit.Test; + +public class ArrayDequeUnitTest { + + @Test + public void whenOffer_addsAtLast() { + final Deque deque = new ArrayDeque<>(); + + deque.offer("first"); + deque.offer("second"); + + assertEquals("second", deque.getLast()); + } + + @Test + public void whenPoll_removesFirst() { + final Deque deque = new ArrayDeque<>(); + + deque.offer("first"); + deque.offer("second"); + + assertEquals("first", deque.poll()); + } + + @Test + public void whenPush_addsAtFirst() { + final Deque deque = new ArrayDeque<>(); + + deque.push("first"); + deque.push("second"); + + assertEquals("second", deque.getFirst()); + } + + @Test + public void whenPop_removesLast() { + final Deque deque = new ArrayDeque<>(); + + deque.push("first"); + deque.push("second"); + + assertEquals("second", deque.pop()); + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUnitTest.java new file mode 100644 index 0000000000..a20526fd9d --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.charstack; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CharStackUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + CharStack charStack = new CharStack(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + CharStack charStack = new CharStack(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + CharStack charStack = new CharStack(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + CharStack charStack = new CharStack(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUsingJavaUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUsingJavaUnitTest.java new file mode 100644 index 0000000000..964b901ae0 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackUsingJavaUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.charstack; + +import static org.junit.Assert.assertEquals; + +import java.util.Stack; + +import org.junit.jupiter.api.Test; + +public class CharStackUsingJavaUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + Stack charStack = new Stack<>(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + Stack charStack = new Stack<>(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + Stack charStack = new Stack<>(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + + Stack charStack = new Stack<>(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackWithArrayUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackWithArrayUnitTest.java new file mode 100644 index 0000000000..df90b8f0a4 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/charstack/CharStackWithArrayUnitTest.java @@ -0,0 +1,65 @@ +package com.baeldung.charstack; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CharStackWithArrayUnitTest { + + @Test + public void whenCharStackIsCreated_thenItHasSize0() { + + CharStackWithArray charStack = new CharStackWithArray(); + + assertEquals(0, charStack.size()); + } + + @Test + public void givenEmptyCharStack_whenElementIsPushed_thenStackSizeisIncreased() { + + CharStackWithArray charStack = new CharStackWithArray(); + + charStack.push('A'); + + assertEquals(1, charStack.size()); + } + + @Test + public void givenEmptyCharStack_when5ElementIsPushed_thenStackSizeis() { + + CharStackWithArray charStack = new CharStackWithArray(); + + charStack.push('A'); + charStack.push('B'); + charStack.push('C'); + charStack.push('D'); + charStack.push('E'); + + assertEquals(5, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() { + + CharStackWithArray charStack = new CharStackWithArray(); + charStack.push('A'); + + char element = charStack.pop(); + + assertEquals('A', element); + assertEquals(0, charStack.size()); + } + + @Test + public void givenCharStack_whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() { + + CharStackWithArray charStack = new CharStackWithArray(); + charStack.push('A'); + + char element = charStack.peek(); + + assertEquals('A', element); + assertEquals(1, charStack.size()); + } + +} diff --git a/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningArraysUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningArraysUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningArraysUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningArraysUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningListsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningListsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningListsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningListsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningMapsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningMapsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningMapsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningMapsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningSetsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningSetsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningSetsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/combiningcollections/CombiningSetsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/DummyEnum.java diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapBenchmarkLiveTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/enummap/EnumMapUnitTest.java diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java new file mode 100644 index 0000000000..5218332d60 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java @@ -0,0 +1,98 @@ +package com.baeldung.hashmapvshashtable; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.junit.Test; + +import com.google.common.collect.Lists; + +public class HashmapVsHashtableDifferenceUnitTest { + + // null values + @Test(expected = NullPointerException.class) + public void givenHashtable_whenAddNullKey_thenNullPointerExceptionThrown() { + Hashtable table = new Hashtable(); + table.put(null, "value"); + } + + @Test(expected = NullPointerException.class) + public void givenHashtable_whenAddNullValue_thenNullPointerExceptionThrown() { + Hashtable table = new Hashtable(); + table.put("key", null); + } + + @Test + public void givenHashmap_whenAddNullKeyAndValue_thenObjectAdded() { + HashMap map = new HashMap(); + map.put(null, "value"); + map.put("key1", null); + map.put("key2", null); + + assertEquals(3, map.size()); + } + + // fail-fast iterator + @Test(expected = ConcurrentModificationException.class) + public void givenHashmap_whenModifyUnderlyingCollection_thenConcurrentModificationExceptionThrown() { + HashMap map = new HashMap(); + map.put("key1", "value1"); + map.put("key2", "value2"); + map.put("key3", "value3"); + + Iterator iterator = map.keySet().iterator(); + while(iterator.hasNext()){ + iterator.next(); + map.put("key4", "value4"); + } + } + + @Test + public void givenHashtable_whenModifyUnderlyingCollection_thenItHasNoEffectOnIteratedCollection() { + Hashtable table = new Hashtable(); + table.put("key1", "value1"); + table.put("key2", "value2"); + + List keysSelected = Lists.newArrayList(); + Enumeration keys = table.keys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + keysSelected.add(key); + + if (key.equals("key1")) { + table.put("key3", "value3"); + } + } + + assertEquals(2, keysSelected.size()); + } + + // synchronized map + @Test + public void givenHashmap_thenCreateSynchronizedMap() { + HashMap map = new HashMap(); + map.put("key1", "value1"); + map.put("key2", "value2"); + map.put("key3", "value3"); + + Set> set = map.entrySet(); + synchronized (map) { + Iterator> it = set.iterator(); + while(it.hasNext()) { + Map.Entry elem = (Map.Entry)it.next(); + } + } + + Map syncMap = Collections.synchronizedMap(map); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/hashtable/HashtableUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/hashtable/HashtableUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/hashtable/HashtableUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/hashtable/HashtableUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/iterators/IteratorsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/iterators/IteratorsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/iterators/IteratorsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/iterators/IteratorsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/java/iterable/IterableSizeUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/java/iterable/IterableSizeUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/java/iterable/IterableSizeUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/java/iterable/IterableSizeUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java new file mode 100644 index 0000000000..7471d9841d --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.queueInterface; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CustomBaeldungQueueUnitTest { + + private CustomBaeldungQueue customQueue; + + @Before + public void setUp() throws Exception { + customQueue = new CustomBaeldungQueue<>(); + } + + @Test + public void givenQueueWithTwoElements_whenElementsRetrieved_checkRetrievalCorrect() { + + customQueue.add(7); + customQueue.add(5); + + int first = customQueue.poll(); + int second = customQueue.poll(); + + assertEquals(7, first); + assertEquals(5, second); + + } +} diff --git a/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java new file mode 100644 index 0000000000..748099e8d1 --- /dev/null +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.queueInterface; + +import org.junit.Before; +import org.junit.Test; + +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +public class PriorityQueueUnitTest { + + + + @Test + public void givenIntegerQueue_whenIntegersOutOfOrder_checkRetrievalOrderIsNatural() { + + PriorityQueue integerQueue = new PriorityQueue<>(); + + integerQueue.add(9); + integerQueue.add(2); + integerQueue.add(4); + + int first = integerQueue.poll(); + int second = integerQueue.poll(); + int third = integerQueue.poll(); + + assertEquals(2, first); + assertEquals(4, second); + assertEquals(9, third); + + + } + + @Test + public void givenStringQueue_whenStringsAddedOutOfNaturalOrder_checkRetrievalOrderNatural() { + + PriorityQueue stringQueue = new PriorityQueue<>(); + + stringQueue.add("banana"); + stringQueue.add("apple"); + stringQueue.add("cherry"); + + String first = stringQueue.poll(); + String second = stringQueue.poll(); + String third = stringQueue.poll(); + + assertEquals("apple", first); + assertEquals("banana", second); + assertEquals("cherry", third); + + + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/removal/RemovalUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/removal/RemovalUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/removal/RemovalUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/removal/RemovalUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/shufflingcollections/ShufflingCollectionsUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/stack_tests/MultithreadingCorrectnessStackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/stack_tests/MultithreadingCorrectnessStackUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/stack_tests/MultithreadingCorrectnessStackUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/stack_tests/MultithreadingCorrectnessStackUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/stack_tests/StackUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/stack_tests/StackUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/stack_tests/StackUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/stack_tests/StackUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java similarity index 97% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java index 84feeb6eaa..fd84503226 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java @@ -1,28 +1,28 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - -public class SynchronizedCollectionUnitTest { - - @Test - public void givenSynchronizedCollection_whenTwoThreadsAddElements_thenCorrectCollectionSize() throws InterruptedException { - Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>()); - - Runnable listOperations = () -> { - syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); - }; - Thread thread1 = new Thread(listOperations); - Thread thread2 = new Thread(listOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncCollection.size()).isEqualTo(12); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedCollectionUnitTest { + + @Test + public void givenSynchronizedCollection_whenTwoThreadsAddElements_thenCorrectCollectionSize() throws InterruptedException { + Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>()); + + Runnable listOperations = () -> { + syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); + }; + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncCollection.size()).isEqualTo(12); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java similarity index 97% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java index 68fc3becd4..72354622ae 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java @@ -1,51 +1,51 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Test; -import static org.assertj.core.api.Assertions.*; - -public class SynchronizedListUnitTest { - - @Test - public void givenSynchronizedList_whenTwoThreadsAddElements_thenCorrectListSize() throws InterruptedException { - List syncList = Collections.synchronizedList(new ArrayList<>()); - - Runnable listOperations = () -> { - syncList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); - }; - Thread thread1 = new Thread(listOperations); - Thread thread2 = new Thread(listOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncList.size()).isEqualTo(12); - } - - @Test - public void givenStringList_whenTwoThreadsIterateOnSynchronizedList_thenCorrectResult() throws InterruptedException { - List syncCollection = Collections.synchronizedList(Arrays.asList("a", "b", "c")); - List uppercasedCollection = new ArrayList<>(); - - Runnable listOperations = () -> { - synchronized (syncCollection) { - syncCollection.forEach((e) -> { - uppercasedCollection.add(e.toUpperCase()); - }); - } - }; - - Thread thread1 = new Thread(listOperations); - Thread thread2 = new Thread(listOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(uppercasedCollection.get(0)).isEqualTo("A"); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedListUnitTest { + + @Test + public void givenSynchronizedList_whenTwoThreadsAddElements_thenCorrectListSize() throws InterruptedException { + List syncList = Collections.synchronizedList(new ArrayList<>()); + + Runnable listOperations = () -> { + syncList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)); + }; + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncList.size()).isEqualTo(12); + } + + @Test + public void givenStringList_whenTwoThreadsIterateOnSynchronizedList_thenCorrectResult() throws InterruptedException { + List syncCollection = Collections.synchronizedList(Arrays.asList("a", "b", "c")); + List uppercasedCollection = new ArrayList<>(); + + Runnable listOperations = () -> { + synchronized (syncCollection) { + syncCollection.forEach((e) -> { + uppercasedCollection.add(e.toUpperCase()); + }); + } + }; + + Thread thread1 = new Thread(listOperations); + Thread thread2 = new Thread(listOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(uppercasedCollection.get(0)).isEqualTo("A"); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java similarity index 96% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java index abfb866e9c..842e253e9e 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java @@ -1,30 +1,30 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.Test; -import static org.assertj.core.api.Assertions.*; - -public class SynchronizedMapUnitTest { - - @Test - public void givenSynchronizedMap_whenTwoThreadsAddElements_thenCorrectMapSize() throws InterruptedException { - Map syncMap = Collections.synchronizedMap(new HashMap<>()); - - Runnable mapOperations = () -> { - syncMap.put(1, "one"); - syncMap.put(2, "two"); - syncMap.put(3, "three"); - - }; - Thread thread1 = new Thread(mapOperations); - Thread thread2 = new Thread(mapOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncMap.size()).isEqualTo(3); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedMapUnitTest { + + @Test + public void givenSynchronizedMap_whenTwoThreadsAddElements_thenCorrectMapSize() throws InterruptedException { + Map syncMap = Collections.synchronizedMap(new HashMap<>()); + + Runnable mapOperations = () -> { + syncMap.put(1, "one"); + syncMap.put(2, "two"); + syncMap.put(3, "three"); + + }; + Thread thread1 = new Thread(mapOperations); + Thread thread2 = new Thread(mapOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncMap.size()).isEqualTo(3); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java similarity index 97% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java index 58a33b207d..f88f58a55b 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java @@ -1,26 +1,26 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import org.junit.Test; -import static org.assertj.core.api.Assertions.*; - -public class SynchronizedSetUnitTest { - - @Test - public void givenSynchronizedSet_whenTwoThreadsAddElements_thenCorrectSetSize() throws InterruptedException { - Set syncSet = Collections.synchronizedSet(new HashSet<>()); - - Runnable setOperations = () -> {syncSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; - Thread thread1 = new Thread(setOperations); - Thread thread2 = new Thread(setOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncSet.size()).isEqualTo(6); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class SynchronizedSetUnitTest { + + @Test + public void givenSynchronizedSet_whenTwoThreadsAddElements_thenCorrectSetSize() throws InterruptedException { + Set syncSet = Collections.synchronizedSet(new HashSet<>()); + + Runnable setOperations = () -> {syncSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; + Thread thread1 = new Thread(setOperations); + Thread thread2 = new Thread(setOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSet.size()).isEqualTo(6); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java similarity index 97% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java index 4b0ed6d8c8..23933b2b4b 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java @@ -1,29 +1,29 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - -public class SynchronizedSortedMapUnitTest { - - @Test - public void givenSynchronizedSorteMap_whenTwoThreadsAddElements_thenCorrectSortedMapSize() throws InterruptedException { - Map syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>()); - - Runnable sortedMapOperations = () -> { - syncSortedMap.put(1, "One"); - syncSortedMap.put(2, "Two"); - syncSortedMap.put(3, "Three"); - }; - Thread thread1 = new Thread(sortedMapOperations); - Thread thread2 = new Thread(sortedMapOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncSortedMap.size()).isEqualTo(3); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedSortedMapUnitTest { + + @Test + public void givenSynchronizedSorteMap_whenTwoThreadsAddElements_thenCorrectSortedMapSize() throws InterruptedException { + Map syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>()); + + Runnable sortedMapOperations = () -> { + syncSortedMap.put(1, "One"); + syncSortedMap.put(2, "Two"); + syncSortedMap.put(3, "Three"); + }; + Thread thread1 = new Thread(sortedMapOperations); + Thread thread2 = new Thread(sortedMapOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSortedMap.size()).isEqualTo(3); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java similarity index 97% rename from core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java index 0e26c6eb1c..3ce1e6ed26 100644 --- a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java +++ b/core-java-modules/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java @@ -1,28 +1,28 @@ -package com.baeldung.synchronizedcollections.test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.SortedSet; -import java.util.TreeSet; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - -public class SynchronizedSortedSetUnitTest { - - @Test - public void givenSynchronizedSortedSet_whenTwoThreadsAddElements_thenCorrectSortedSetSize() throws InterruptedException { - SortedSet syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>()); - - Runnable sortedSetOperations = () -> {syncSortedSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; - sortedSetOperations.run(); - sortedSetOperations.run(); - Thread thread1 = new Thread(sortedSetOperations); - Thread thread2 = new Thread(sortedSetOperations); - thread1.start(); - thread2.start(); - thread1.join(); - thread2.join(); - - assertThat(syncSortedSet.size()).isEqualTo(6); - } -} +package com.baeldung.synchronizedcollections.test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SynchronizedSortedSetUnitTest { + + @Test + public void givenSynchronizedSortedSet_whenTwoThreadsAddElements_thenCorrectSortedSetSize() throws InterruptedException { + SortedSet syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>()); + + Runnable sortedSetOperations = () -> {syncSortedSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));}; + sortedSetOperations.run(); + sortedSetOperations.run(); + Thread thread1 = new Thread(sortedSetOperations); + Thread thread2 = new Thread(sortedSetOperations); + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + assertThat(syncSortedSet.size()).isEqualTo(6); + } +} diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsConcatenateUnitTest.java b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsConcatenateUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsConcatenateUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsConcatenateUnitTest.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/JoinSplitCollectionsUnitTest.java b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/JoinSplitCollectionsUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/collections/JoinSplitCollectionsUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/JoinSplitCollectionsUnitTest.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/README.md b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/README.md similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/collections/README.md rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/collections/README.md diff --git a/core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java diff --git a/core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java b/core-java-modules/core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java rename to core-java-modules/core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java diff --git a/core-java-concurrency-collections/.gitignore b/core-java-modules/core-java-concurrency-advanced/.gitignore similarity index 100% rename from core-java-concurrency-collections/.gitignore rename to core-java-modules/core-java-concurrency-advanced/.gitignore diff --git a/core-java-concurrency/README.md b/core-java-modules/core-java-concurrency-advanced/README.md similarity index 53% rename from core-java-concurrency/README.md rename to core-java-modules/core-java-concurrency-advanced/README.md index 2db7b91cde..8e99858693 100644 --- a/core-java-concurrency/README.md +++ b/core-java-modules/core-java-concurrency-advanced/README.md @@ -1,33 +1,25 @@ ========= -## Core Java Concurrency Examples +## Core Java Concurrency Advanced Examples ### Relevant Articles: -- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture) -- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial) - [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava) -- [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future) - [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch) - [Guide to java.util.concurrent.Locks](http://www.baeldung.com/java-concurrent-locks) - [An Introduction to ThreadLocal in Java](http://www.baeldung.com/java-threadlocal) -- [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep) - [LongAdder and LongAccumulator in Java](http://www.baeldung.com/java-longadder-and-longaccumulator) - [The Dining Philosophers Problem in Java](http://www.baeldung.com/java-dining-philoshophers) - [Guide to the Java Phaser](http://www.baeldung.com/java-phaser) -- [Guide to Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized) - [An Introduction to Atomic Variables in Java](http://www.baeldung.com/java-atomic-variables) - [CyclicBarrier in Java](http://www.baeldung.com/java-cyclic-barrier) -- [Guide to Volatile Keyword in Java](http://www.baeldung.com/java-volatile) -- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent) +- [Guide to the Volatile Keyword in Java](http://www.baeldung.com/java-volatile) - [Semaphores in Java](http://www.baeldung.com/java-semaphore) - [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread) -- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread) -- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop) -- [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads) -- [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify) - [Priority-based Job Scheduling in Java](http://www.baeldung.com/java-priority-job-schedule) -- [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) - [Brief Introduction to Java Thread.yield()](https://www.baeldung.com/java-thread-yield) - [Print Even and Odd Numbers Using 2 Threads](https://www.baeldung.com/java-even-odd-numbers-with-2-threads) - [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) +- [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) +- [Passing Parameters to Java Threads](https://www.baeldung.com/java-thread-parameters) diff --git a/core-java-concurrency/pom.xml b/core-java-modules/core-java-concurrency-advanced/pom.xml similarity index 76% rename from core-java-concurrency/pom.xml rename to core-java-modules/core-java-concurrency-advanced/pom.xml index bd22253c2c..a3ac7aa88a 100644 --- a/core-java-concurrency/pom.xml +++ b/core-java-modules/core-java-concurrency-advanced/pom.xml @@ -2,16 +2,16 @@ 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-concurrency + core-java-concurrency-advanced 0.1.0-SNAPSHOT + core-java-concurrency-advanced jar - core-java-concurrency com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java @@ -47,10 +47,20 @@ ${avaitility.version} test + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator-annprocess.version} + - core-java-concurrency + core-java-concurrency-advanced src/main/resources @@ -69,6 +79,8 @@ 3.6.1 1.7.0 + 1.19 + 1.19 diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java similarity index 94% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java index e3a1629ce1..ef6b7ee8c8 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java @@ -1,13 +1,13 @@ -package com.baeldung.concurrent.atomic; - -public class SafeCounterWithLock { - private volatile int counter; - - int getValue() { - return counter; - } - - synchronized void increment() { - counter++; - } -} +package com.baeldung.concurrent.atomic; + +public class SafeCounterWithLock { + private volatile int counter; + + int getValue() { + return counter; + } + + synchronized void increment() { + counter++; + } +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java similarity index 96% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java index 18ade35efb..8b2aebba7c 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java @@ -1,21 +1,21 @@ -package com.baeldung.concurrent.atomic; - -import java.util.concurrent.atomic.AtomicInteger; - -public class SafeCounterWithoutLock { - private final AtomicInteger counter = new AtomicInteger(0); - - int getValue() { - return counter.get(); - } - - void increment() { - while(true) { - int existingValue = getValue(); - int newValue = existingValue + 1; - if(counter.compareAndSet(existingValue, newValue)) { - return; - } - } - } -} +package com.baeldung.concurrent.atomic; + +import java.util.concurrent.atomic.AtomicInteger; + +public class SafeCounterWithoutLock { + private final AtomicInteger counter = new AtomicInteger(0); + + int getValue() { + return counter.get(); + } + + void increment() { + while(true) { + int existingValue = getValue(); + int newValue = existingValue + 1; + if(counter.compareAndSet(existingValue, newValue)) { + return; + } + } + } +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java similarity index 94% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java index 500ef5bd7e..290c26b73d 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java @@ -1,13 +1,13 @@ -package com.baeldung.concurrent.atomic; - -public class UnsafeCounter { - private int counter; - - int getValue() { - return counter; - } - - void increment() { - counter++; - } -} +package com.baeldung.concurrent.atomic; + +public class UnsafeCounter { + private int counter; + + int getValue() { + return counter; + } + + void increment() { + counter++; + } +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java new file mode 100644 index 0000000000..a548b5d4a7 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java @@ -0,0 +1,20 @@ +package com.baeldung.concurrent.parameter; + +import java.util.concurrent.Callable; +import java.util.stream.IntStream; + +public class AverageCalculator implements Callable { + + int[] numbers; + + public AverageCalculator(int... parameter) { + this.numbers = parameter == null ? new int[0] : parameter; + } + + @Override + public Double call() throws Exception { + return IntStream.of(this.numbers) + .average() + .orElse(0d); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java new file mode 100644 index 0000000000..73c61f3fb1 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java @@ -0,0 +1,32 @@ +package com.baeldung.concurrent.parameter; + +import java.util.concurrent.Callable; +import java.util.stream.IntStream; + +public class ParameterizedThreadExample { + + public static void parameterisedThreadAnonymousClass() { + final String parameter = "123"; + Thread parameterizedThread = new Thread(new Runnable() { + + @Override + public void run() { + System.out.println(Thread.currentThread() + .getName() + " : " + parameter); + } + }); + + parameterizedThread.start(); + } + + public static Callable sumCalculator(int... numbers) { + return () -> numbers != null ? IntStream.of(numbers) + .sum() : 0; + } + + public static Callable averageCalculator(int... numbers) { + return () -> numbers != null ? IntStream.of(numbers) + .average() + .orElse(0d) : 0d; + } +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java diff --git a/core-java/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java similarity index 100% rename from core-java/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java diff --git a/core-java/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java similarity index 100% rename from core-java/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java diff --git a/core-java/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java similarity index 100% rename from core-java/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/Context.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/Context.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/UserRepository.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/UserRepository.java diff --git a/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java similarity index 100% rename from core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java diff --git a/core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java similarity index 100% rename from core-java/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/CountingTask.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/CountingTask.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/TreeNode.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/TreeNode.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/TreeNode.java rename to core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/TreeNode.java diff --git a/core-java-concurrency/src/main/java/log4j.properties b/core-java-modules/core-java-concurrency-advanced/src/main/java/log4j.properties similarity index 100% rename from core-java-concurrency/src/main/java/log4j.properties rename to core-java-modules/core-java-concurrency-advanced/src/main/java/log4j.properties diff --git a/core-java-concurrency/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-advanced/src/main/resources/logback.xml similarity index 100% rename from core-java-concurrency/src/main/resources/logback.xml rename to core-java-modules/core-java-concurrency-advanced/src/main/resources/logback.xml diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java similarity index 97% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java index 4eead471f8..c3c44b40cf 100644 --- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java +++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java @@ -1,38 +1,38 @@ -package com.baeldung.concurrent.atomic; - -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import org.junit.Test; - -public class ThreadSafeCounterIntegrationTest { - - @Test - public void givenMultiThread_whenSafeCounterWithLockIncrement() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(3); - SafeCounterWithLock safeCounter = new SafeCounterWithLock(); - - IntStream.range(0, 1000) - .forEach(count -> service.submit(safeCounter::increment)); - service.awaitTermination(100, TimeUnit.MILLISECONDS); - - assertEquals(1000, safeCounter.getValue()); - } - - @Test - public void givenMultiThread_whenSafeCounterWithoutLockIncrement() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(3); - SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock(); - - IntStream.range(0, 1000) - .forEach(count -> service.submit(safeCounter::increment)); - service.awaitTermination(100, TimeUnit.MILLISECONDS); - - assertEquals(1000, safeCounter.getValue()); - } - -} +package com.baeldung.concurrent.atomic; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Test; + +public class ThreadSafeCounterIntegrationTest { + + @Test + public void givenMultiThread_whenSafeCounterWithLockIncrement() throws InterruptedException { + ExecutorService service = Executors.newFixedThreadPool(3); + SafeCounterWithLock safeCounter = new SafeCounterWithLock(); + + IntStream.range(0, 1000) + .forEach(count -> service.submit(safeCounter::increment)); + service.awaitTermination(100, TimeUnit.MILLISECONDS); + + assertEquals(1000, safeCounter.getValue()); + } + + @Test + public void givenMultiThread_whenSafeCounterWithoutLockIncrement() throws InterruptedException { + ExecutorService service = Executors.newFixedThreadPool(3); + SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock(); + + IntStream.range(0, 1000) + .forEach(count -> service.submit(safeCounter::increment)); + service.awaitTermination(100, TimeUnit.MILLISECONDS); + + assertEquals(1000, safeCounter.getValue()); + } + +} diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java similarity index 97% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java index cc7cc18bb5..bf451e58de 100644 --- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java +++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java @@ -1,33 +1,33 @@ -package com.baeldung.concurrent.atomic; - -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; - -import org.junit.Test; - -/** - * This test shows the behaviour of a thread-unsafe class in a multithreaded scenario. We are calling - * the increment methods 1000 times from a pool of 3 threads. In most of the cases, the counter will - * less than 1000, because of lost updates, however, occasionally it may reach 1000, when no threads - * called the method simultaneously. This may cause the build to fail occasionally. Hence excluding this - * test from build by adding this in manual test - */ -public class ThreadUnsafeCounterManualTest { - - @Test - public void givenMultiThread_whenUnsafeCounterIncrement() throws InterruptedException { - ExecutorService service = Executors.newFixedThreadPool(3); - UnsafeCounter unsafeCounter = new UnsafeCounter(); - - IntStream.range(0, 1000) - .forEach(count -> service.submit(unsafeCounter::increment)); - service.awaitTermination(100, TimeUnit.MILLISECONDS); - - assertEquals(1000, unsafeCounter.getValue()); - } - -} +package com.baeldung.concurrent.atomic; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Test; + +/** + * This test shows the behaviour of a thread-unsafe class in a multithreaded scenario. We are calling + * the increment methods 1000 times from a pool of 3 threads. In most of the cases, the counter will + * less than 1000, because of lost updates, however, occasionally it may reach 1000, when no threads + * called the method simultaneously. This may cause the build to fail occasionally. Hence excluding this + * test from build by adding this in manual test + */ +public class ThreadUnsafeCounterManualTest { + + @Test + public void givenMultiThread_whenUnsafeCounterIncrement() throws InterruptedException { + ExecutorService service = Executors.newFixedThreadPool(3); + UnsafeCounter unsafeCounter = new UnsafeCounter(); + + IntStream.range(0, 1000) + .forEach(count -> service.submit(unsafeCounter::increment)); + service.awaitTermination(100, TimeUnit.MILLISECONDS); + + assertEquals(1000, unsafeCounter.getValue()); + } + +} diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java diff --git a/core-java/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java new file mode 100644 index 0000000000..21b374e609 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.parameters; + +import com.baeldung.concurrent.parameter.AverageCalculator; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertEquals; + +public class ParameterizedThreadUnitTest { + + @Test + public void whenSendingParameterToCallable_thenSuccessful() throws Exception { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Future result = executorService.submit(new AverageCalculator(1, 2, 3)); + try { + assertEquals(Double.valueOf(2.0), result.get()); + } finally { + executorService.shutdown(); + } + } + + @Test + public void whenParametersToThreadWithLamda_thenParametersPassedCorrectly() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + int[] numbers = new int[] { 4, 5, 6 }; + try { + Future sumResult = executorService.submit(() -> IntStream.of(numbers) + .sum()); + Future averageResult = executorService.submit(() -> IntStream.of(numbers) + .average() + .orElse(0d)); + assertEquals(Integer.valueOf(15), sumResult.get()); + assertEquals(Double.valueOf(5.0), averageResult.get()); + } finally { + executorService.shutdown(); + } + } + +} diff --git a/core-java/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java rename to core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/resources/.gitignore b/core-java-modules/core-java-concurrency-advanced/src/test/resources/.gitignore similarity index 100% rename from core-java-concurrency-collections/src/test/resources/.gitignore rename to core-java-modules/core-java-concurrency-advanced/src/test/resources/.gitignore diff --git a/core-java-concurrency/.gitignore b/core-java-modules/core-java-concurrency-basic/.gitignore similarity index 100% rename from core-java-concurrency/.gitignore rename to core-java-modules/core-java-concurrency-basic/.gitignore diff --git a/core-java-modules/core-java-concurrency-basic/README.md b/core-java-modules/core-java-concurrency-basic/README.md new file mode 100644 index 0000000000..6fa702fbe7 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/README.md @@ -0,0 +1,19 @@ +========= + +## Core Java Concurrency Basic Examples + +### Relevant Articles: +- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture) +- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial) +- [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future) +- [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep) +- [Guide to the Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized) +- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent) +- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread) +- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop) +- [ExecutorService – Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads) +- [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify) +- [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) diff --git a/core-java-modules/core-java-concurrency-basic/pom.xml b/core-java-modules/core-java-concurrency-basic/pom.xml new file mode 100644 index 0000000000..aea4bef6a7 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + com.baeldung + core-java-concurrency-basic + 0.1.0-SNAPSHOT + core-java-concurrency-basic + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + com.jayway.awaitility + awaitility + ${avaitility.version} + test + + + + + core-java-concurrency-basic + + + src/main/resources + true + + + + + + + 3.5 + + 3.6.1 + 1.7.0 + + + diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/delay/Delay.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/delay/Delay.java new file mode 100644 index 0000000000..1689c09f51 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/delay/Delay.java @@ -0,0 +1,93 @@ +package com.baeldung.concurrent.delay; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class Delay { + + public static void main(String args[]) throws InterruptedException { + + threadSleep(4, 1); + + timeunitSleep(4, 1); + + delayedServiceTask(5); + + fixedRateServiceTask(5); + + System.out.println("Done."); + + return; + + } + + private static void threadSleep(Integer iterations, Integer secondsToSleep) { + + for (Integer i = 0; i < iterations; i++) { + + System.out.println("This is loop iteration number " + i.toString()); + + try { + Thread.sleep(secondsToSleep * 1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + } + + } + + private static void timeunitSleep(Integer iterations, Integer secondsToSleep) { + + for (Integer i = 0; i < iterations; i++) { + + System.out.println("This is loop iteration number " + i.toString()); + + try { + TimeUnit.SECONDS.sleep(secondsToSleep); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + } + + } + + private static void delayedServiceTask(Integer delayInSeconds) { + + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + executorService.schedule(Delay::someTask1, delayInSeconds, TimeUnit.SECONDS); + + executorService.shutdown(); + } + + private static void fixedRateServiceTask(Integer delayInSeconds) { + + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + ScheduledFuture sf = executorService.scheduleAtFixedRate(Delay::someTask2, 0, delayInSeconds, + TimeUnit.SECONDS); + + try { + TimeUnit.SECONDS.sleep(20); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + + sf.cancel(true); + + executorService.shutdown(); + } + + private static void someTask1() { + System.out.println("Task 1 completed."); + } + + private static void someTask2() { + System.out.println("Task 2 completed."); + } + +} \ No newline at end of file diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/Invoker.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/Invoker.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/Invoker.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/Invoker.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/Task.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/Task.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FutureDemo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FutureDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FutureDemo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FutureDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Task.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Task.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Task.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Task.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java new file mode 100644 index 0000000000..5fcb28cd2a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java @@ -0,0 +1,86 @@ +package com.baeldung.concurrent.threadsafety.application; + +import com.baeldung.concurrent.threadsafety.callables.AtomicCounterCallable; +import com.baeldung.concurrent.threadsafety.mathutils.MathUtils; +import com.baeldung.concurrent.threadsafety.callables.CounterCallable; +import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable; +import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable; +import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable; +import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable; +import com.baeldung.concurrent.threadsafety.services.AtomicCounter; +import com.baeldung.concurrent.threadsafety.services.Counter; +import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import com.baeldung.concurrent.threadsafety.services.MessageService; +import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; +import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class Application { + + public static void main(String[] args) throws InterruptedException, ExecutionException { + + new Thread(() -> { + System.out.println(MathUtils.factorial(10)); + }).start(); + new Thread(() -> { + System.out.println(MathUtils.factorial(5)); + }).start(); + + ExecutorService executorService = Executors.newFixedThreadPool(10); + MessageService messageService = new MessageService("Welcome to Baeldung!"); + Future future1 = (Future) executorService.submit(new MessageServiceCallable(messageService)); + Future future2 = (Future) executorService.submit(new MessageServiceCallable(messageService)); + System.out.println(future1.get()); + System.out.println(future2.get()); + + Counter counter = new Counter(); + Future future3 = (Future) executorService.submit(new CounterCallable(counter)); + Future future4 = (Future) executorService.submit(new CounterCallable(counter)); + System.out.println(future3.get()); + System.out.println(future4.get()); + + ExtrinsicLockCounter extrinsicLockCounter = new ExtrinsicLockCounter(); + Future future5 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); + Future future6 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); + System.out.println(future5.get()); + System.out.println(future6.get()); + + ReentrantLockCounter reentrantLockCounter = new ReentrantLockCounter(); + Future future7 = (Future) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter)); + Future future8 = (Future) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter)); + System.out.println(future7.get()); + System.out.println(future8.get()); + + ReentrantReadWriteLockCounter reentrantReadWriteLockCounter = new ReentrantReadWriteLockCounter(); + Future future9 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter)); + Future future10 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter)); + System.out.println(future9.get()); + System.out.println(future10.get()); + + AtomicCounter atomicCounter = new AtomicCounter(); + Future future11 = (Future) executorService.submit(new AtomicCounterCallable(atomicCounter)); + Future future12 = (Future) executorService.submit(new AtomicCounterCallable(atomicCounter)); + System.out.println(future11.get()); + System.out.println(future12.get()); + + Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>()); + Thread thread11 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6))); + Thread thread12 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6))); + thread11.start(); + thread12.start(); + + Map concurrentMap = new ConcurrentHashMap<>(); + concurrentMap.put("1", "one"); + concurrentMap.put("2", "two"); + concurrentMap.put("3", "three"); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java new file mode 100644 index 0000000000..27f7bf598e --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.AtomicCounter; +import java.util.concurrent.Callable; + +public class AtomicCounterCallable implements Callable { + + private final AtomicCounter counter; + + public AtomicCounterCallable(AtomicCounter counter) { + this.counter = counter; + } + + @Override + public Integer call() throws Exception { + counter.incrementCounter(); + return counter.getCounter(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java new file mode 100644 index 0000000000..feca4d7db5 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.Counter; +import java.util.concurrent.Callable; + +public class CounterCallable implements Callable { + + private final Counter counter; + + public CounterCallable(Counter counter) { + this.counter = counter; + } + + @Override + public Integer call() throws Exception { + counter.incrementCounter(); + return counter.getCounter(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java new file mode 100644 index 0000000000..370e5d1f00 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import java.util.concurrent.Callable; + +public class ExtrinsicLockCounterCallable implements Callable { + + private final ExtrinsicLockCounter counter; + + public ExtrinsicLockCounterCallable(ExtrinsicLockCounter counter) { + this.counter = counter; + } + + @Override + public Integer call() throws Exception { + counter.incrementCounter(); + return counter.getCounter(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java new file mode 100644 index 0000000000..5fff2de0c8 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.MessageService; +import java.util.concurrent.Callable; + +public class MessageServiceCallable implements Callable { + + private final MessageService messageService; + + public MessageServiceCallable(MessageService messageService) { + this.messageService = messageService; + + } + + @Override + public String call() { + return messageService.getMesssage(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java new file mode 100644 index 0000000000..f0948daa09 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java @@ -0,0 +1,20 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; +import java.util.concurrent.Callable; + +public class ReentranReadWriteLockCounterCallable implements Callable { + + private final ReentrantReadWriteLockCounter counter; + + public ReentranReadWriteLockCounterCallable(ReentrantReadWriteLockCounter counter) { + this.counter = counter; + } + + @Override + public Integer call() throws Exception { + counter.incrementCounter(); + return counter.getCounter(); + } + +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java new file mode 100644 index 0000000000..572d6ad22f --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.threadsafety.callables; + +import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; +import java.util.concurrent.Callable; + +public class ReentrantLockCounterCallable implements Callable { + + private final ReentrantLockCounter counter; + + public ReentrantLockCounterCallable(ReentrantLockCounter counter) { + this.counter = counter; + } + + @Override + public Integer call() throws Exception { + counter.incrementCounter(); + return counter.getCounter(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java new file mode 100644 index 0000000000..fa84c9c04d --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java @@ -0,0 +1,14 @@ +package com.baeldung.concurrent.threadsafety.mathutils; + +import java.math.BigInteger; + +public class MathUtils { + + public static BigInteger factorial(int number) { + BigInteger f = new BigInteger("1"); + for (int i = 2; i <= number; i++) { + f = f.multiply(BigInteger.valueOf(i)); + } + return f; + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java new file mode 100644 index 0000000000..0e95859265 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.threadsafety.services; + +import java.util.concurrent.atomic.AtomicInteger; + +public class AtomicCounter { + + private final AtomicInteger counter = new AtomicInteger(); + + public AtomicCounter() {} + + public void incrementCounter() { + counter.incrementAndGet(); + } + + public synchronized int getCounter() { + return counter.get(); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java new file mode 100644 index 0000000000..52122ae049 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.threadsafety.services; + +public class Counter { + + private volatile int counter; + + public Counter() { + this.counter = 0; + } + + public synchronized void incrementCounter() { + counter += 1; + } + + public int getCounter() { + return counter; + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java new file mode 100644 index 0000000000..0a6ff3f60e --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.threadsafety.services; + +public class ExtrinsicLockCounter { + + private int counter; + private final Object lock = new Object(); + + public ExtrinsicLockCounter() { + this.counter = 0; + } + + public void incrementCounter() { + synchronized (lock) { + counter += 1; + } + } + + public int getCounter() { + synchronized (lock) { + return counter; + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java new file mode 100644 index 0000000000..a2b5174a9b --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java @@ -0,0 +1,14 @@ +package com.baeldung.concurrent.threadsafety.services; + +public class MessageService { + + private final String message; + + public MessageService(String message) { + this.message = message; + } + + public String getMesssage() { + return message; + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java new file mode 100644 index 0000000000..346cb14c35 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java @@ -0,0 +1,26 @@ +package com.baeldung.concurrent.threadsafety.services; + +import java.util.concurrent.locks.ReentrantLock; + +public class ReentrantLockCounter { + + private int counter; + private final ReentrantLock reLock = new ReentrantLock(true); + + public ReentrantLockCounter() { + this.counter = 0; + } + + public void incrementCounter() { + reLock.lock(); + try { + counter += 1; + } finally { + reLock.unlock(); + } + } + + public int getCounter() { + return counter; + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java new file mode 100644 index 0000000000..5e251441b5 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java @@ -0,0 +1,34 @@ +package com.baeldung.concurrent.threadsafety.services; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReentrantReadWriteLockCounter { + + private int counter; + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); + private final Lock readLock = rwLock.readLock(); + private final Lock writeLock = rwLock.writeLock(); + + public ReentrantReadWriteLockCounter() { + this.counter = 0; + } + + public void incrementCounter() { + writeLock.lock(); + try { + counter += 1; + } finally { + writeLock.unlock(); + } + } + + public int getCounter() { + readLock.lock(); + try { + return counter; + } finally { + readLock.unlock(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java new file mode 100644 index 0000000000..7e87214590 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java @@ -0,0 +1,14 @@ +package com.baeldung.concurrent.threadsafety.services; + +public class StateHolder { + + private final String state; + + public StateHolder(String state) { + this.state = state; + } + + public String getState() { + return state; + } +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java similarity index 100% rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java diff --git a/core-java-io/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-basic/src/main/resources/logback.xml similarity index 100% rename from core-java-io/src/main/resources/logback.xml rename to core-java-modules/core-java-concurrency-basic/src/main/resources/logback.xml diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java new file mode 100644 index 0000000000..176151083c --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import com.baeldung.concurrent.threadsafety.callables.CounterCallable; +import com.baeldung.concurrent.threadsafety.services.Counter; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class CounterTest { + + @Test + public void whenCalledIncrementCounter_thenCorrect() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + Counter counter = new Counter(); + Future future1 = (Future) executorService.submit(new CounterCallable(counter)); + Future future2 = (Future) executorService.submit(new CounterCallable(counter)); + + assertThat(future1.get()).isEqualTo(1); + assertThat(future2.get()).isEqualTo(2); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java new file mode 100644 index 0000000000..e34eb250bf --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable; +import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class ExtrinsicLockCounterTest { + + @Test + public void whenCalledIncrementCounter_thenCorrect() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + ExtrinsicLockCounter counter = new ExtrinsicLockCounter(); + Future future1 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter)); + Future future2 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter)); + + assertThat(future1.get()).isEqualTo(1); + assertThat(future2.get()).isEqualTo(2); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java new file mode 100644 index 0000000000..2708152906 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java @@ -0,0 +1,13 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import com.baeldung.concurrent.threadsafety.mathutils.MathUtils; +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class MathUtilsTest { + + @Test + public void whenCalledFactorialMethod_thenCorrect() { + assertThat(MathUtils.factorial(2)).isEqualTo(2); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java new file mode 100644 index 0000000000..e62206c09a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable; +import com.baeldung.concurrent.threadsafety.services.MessageService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class MessageServiceTest { + + @Test + public void whenCalledgetMessage_thenCorrect() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + MessageService messageService = new MessageService("Welcome to Baeldung!"); + Future future1 = (Future) executorService.submit(new MessageServiceCallable(messageService)); + Future future2 = (Future) executorService.submit(new MessageServiceCallable(messageService)); + + assertThat(future1.get()).isEqualTo("Welcome to Baeldung!"); + assertThat(future2.get()).isEqualTo("Welcome to Baeldung!"); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java new file mode 100644 index 0000000000..20fa2c74da --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable; +import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class ReentrantLockCounterTest { + + @Test + public void whenCalledIncrementCounter_thenCorrect() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + ReentrantLockCounter counter = new ReentrantLockCounter(); + Future future1 = (Future) executorService.submit(new ReentrantLockCounterCallable(counter)); + Future future2 = (Future) executorService.submit(new ReentrantLockCounterCallable(counter)); + + assertThat(future1.get()).isEqualTo(1); + assertThat(future2.get()).isEqualTo(2); + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java new file mode 100644 index 0000000000..6113473cac --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java @@ -0,0 +1,24 @@ +package com.baeldung.concurrent.threadsafety.tests; + +import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable; +import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class ReentrantReadWriteLockCounterTest { + + @Test + public void whenCalledIncrementCounter_thenCorrect() throws Exception { + ExecutorService executorService = Executors.newFixedThreadPool(2); + ReentrantReadWriteLockCounter counter = new ReentrantReadWriteLockCounter(); + Future future1 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(counter)); + Future future2 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(counter)); + + assertThat(future1.get()).isEqualTo(1); + assertThat(future2.get()).isEqualTo(2); + } + +} diff --git a/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java diff --git a/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java similarity index 100% rename from core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java diff --git a/core-java-concurrency/src/test/resources/.gitignore b/core-java-modules/core-java-concurrency-basic/src/test/resources/.gitignore similarity index 100% rename from core-java-concurrency/src/test/resources/.gitignore rename to core-java-modules/core-java-concurrency-basic/src/test/resources/.gitignore diff --git a/core-java-sun/.gitignore b/core-java-modules/core-java-concurrency-collections/.gitignore similarity index 100% rename from core-java-sun/.gitignore rename to core-java-modules/core-java-concurrency-collections/.gitignore diff --git a/core-java-concurrency-collections/README.md b/core-java-modules/core-java-concurrency-collections/README.md similarity index 100% rename from core-java-concurrency-collections/README.md rename to core-java-modules/core-java-concurrency-collections/README.md diff --git a/core-java-concurrency-collections/pom.xml b/core-java-modules/core-java-concurrency-collections/pom.xml similarity index 98% rename from core-java-concurrency-collections/pom.xml rename to core-java-modules/core-java-concurrency-collections/pom.xml index 9473de8c51..27aae4ea6c 100644 --- a/core-java-concurrency-collections/pom.xml +++ b/core-java-modules/core-java-concurrency-collections/pom.xml @@ -4,14 +4,14 @@ com.baeldung core-java-concurrency-collections 0.1.0-SNAPSHOT - jar core-java-concurrency-collections + jar com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/BlockingQueueUsage.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/BlockingQueueUsage.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/BlockingQueueUsage.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/BlockingQueueUsage.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersConsumer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersConsumer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersConsumer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersConsumer.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersProducer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersProducer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersProducer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/blockingqueue/NumbersProducer.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayObject.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayObject.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayObject.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayObject.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueConsumer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueConsumer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueConsumer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueConsumer.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueProducer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueProducer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueProducer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/delayqueue/DelayQueueProducer.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/Event.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/Event.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/Event.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/Event.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Consumer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Consumer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Consumer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Consumer.java diff --git a/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Producer.java b/core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Producer.java similarity index 100% rename from core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Producer.java rename to core-java-modules/core-java-concurrency-collections/src/main/java/com/baeldung/transferqueue/Producer.java diff --git a/core-java-concurrency-collections/src/main/resources/logback.xml b/core-java-modules/core-java-concurrency-collections/src/main/resources/logback.xml similarity index 100% rename from core-java-concurrency-collections/src/main/resources/logback.xml rename to core-java-modules/core-java-concurrency-collections/src/main/resources/logback.xml diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListUnitTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListUnitTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListUnitTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/copyonwrite/CopyOnWriteArrayListUnitTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/delayqueue/DelayQueueIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/delayqueue/DelayQueueIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/delayqueue/DelayQueueIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/delayqueue/DelayQueueIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/synchronousqueue/SynchronousQueueIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/synchronousqueue/SynchronousQueueIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/synchronousqueue/SynchronousQueueIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/synchronousqueue/SynchronousQueueIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/java/com/baeldung/transferqueue/TransferQueueIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/transferqueue/TransferQueueIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/com/baeldung/transferqueue/TransferQueueIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/com/baeldung/transferqueue/TransferQueueIntegrationTest.java diff --git a/core-java-concurrency-collections/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java b/core-java-modules/core-java-concurrency-collections/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java similarity index 100% rename from core-java-concurrency-collections/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java rename to core-java-modules/core-java-concurrency-collections/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java diff --git a/core-java-io/src/test/resources/.gitignore b/core-java-modules/core-java-concurrency-collections/src/test/resources/.gitignore similarity index 100% rename from core-java-io/src/test/resources/.gitignore rename to core-java-modules/core-java-concurrency-collections/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml new file mode 100644 index 0000000000..2e5200944a --- /dev/null +++ b/core-java-modules/core-java-exceptions/pom.xml @@ -0,0 +1,35 @@ + + 4.0.0 + com.baeldung.exception.numberformat + core-java-exceptions + 0.0.1-SNAPSHOT + core-java-exceptions + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + junit + junit + ${junit.version} + test + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + 3.9 + + + diff --git a/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/RootCauseFinder.java b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/RootCauseFinder.java new file mode 100644 index 0000000000..cf449110e6 --- /dev/null +++ b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/RootCauseFinder.java @@ -0,0 +1,98 @@ +package com.baeldung.exceptions; + +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeParseException; +import java.util.Objects; + +/** + * Utility class to find root cause exceptions. + */ +public class RootCauseFinder { + + private RootCauseFinder() { + } + + public static Throwable findCauseUsingPlainJava(Throwable throwable) { + Objects.requireNonNull(throwable); + Throwable rootCause = throwable; + while (rootCause.getCause() != null && rootCause.getCause() != rootCause) { + rootCause = rootCause.getCause(); + } + return rootCause; + } + + /** + * Calculates the age of a person from a given date. + */ + static class AgeCalculator { + + private AgeCalculator() { + } + + public static int calculateAge(String birthDate) { + if (birthDate == null || birthDate.isEmpty()) { + throw new IllegalArgumentException(); + } + + try { + return Period + .between(parseDate(birthDate), LocalDate.now()) + .getYears(); + } catch (DateParseException ex) { + throw new CalculationException(ex); + } + } + + private static LocalDate parseDate(String birthDateAsString) { + + LocalDate birthDate; + try { + birthDate = LocalDate.parse(birthDateAsString); + } catch (DateTimeParseException ex) { + throw new InvalidFormatException(birthDateAsString, ex); + } + + if (birthDate.isAfter(LocalDate.now())) { + throw new DateOutOfRangeException(birthDateAsString); + } + + return birthDate; + } + + } + + static class CalculationException extends RuntimeException { + + CalculationException(DateParseException ex) { + super(ex); + } + } + + static class DateParseException extends RuntimeException { + + DateParseException(String input) { + super(input); + } + + DateParseException(String input, Throwable thr) { + super(input, thr); + } + } + + static class InvalidFormatException extends DateParseException { + + InvalidFormatException(String input, Throwable thr) { + super("Invalid date format: " + input, thr); + } + } + + static class DateOutOfRangeException extends DateParseException { + + DateOutOfRangeException(String date) { + super("Date out of range: " + date); + } + + } + +} diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java new file mode 100644 index 0000000000..6dcd0d72e0 --- /dev/null +++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.exception.error; + +import org.junit.Assert; +import org.junit.Test; + +public class ErrorGeneratorUnitTest { + + @Test(expected = AssertionError.class) + public void whenError_thenIsNotCaughtByCatchException() { + try { + throw new AssertionError(); + } catch (Exception e) { + Assert.fail(); // errors are not caught by catch exception + } + } + + @Test + public void whenError_thenIsCaughtByCatchError() { + try { + throw new AssertionError(); + } catch (Error e) { + // caught! -> test pass + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java new file mode 100644 index 0000000000..cb26bf451a --- /dev/null +++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java @@ -0,0 +1,154 @@ +package com.baeldung.exception.numberformat; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; +import java.util.logging.Logger; + +import org.junit.Test; + +/** + * A set of examples tested to show cases where NumberFormatException is thrown and not thrown. + */ +public class NumberFormatExceptionUnitTest { + + Logger LOG = Logger.getLogger(NumberFormatExceptionUnitTest.class.getName()); + + /* ---INTEGER FAIL CASES--- */ + @Test(expected = NumberFormatException.class) + public void givenByteConstructor_whenAlphabetAsInput_thenFail() { + Byte byteInt = new Byte("one"); + } + + @Test(expected = NumberFormatException.class) + public void givenShortConstructor_whenSpaceInInput_thenFail() { + Short shortInt = new Short("2 "); + } + + @Test(expected = NumberFormatException.class) + public void givenParseIntMethod_whenSpaceInInput_thenFail() { + Integer aIntPrim = Integer.parseInt("6000 "); + } + + @Test(expected = NumberFormatException.class) + public void givenParseIntMethod_whenUnderscoreInInput_thenFail() { + int bIntPrim = Integer.parseInt("_6000"); + } + + @Test(expected = NumberFormatException.class) + public void givenIntegerValueOfMethod_whenCommaInInput_thenFail() { + Integer cIntPrim = Integer.valueOf("6,000"); + } + + @Test(expected = NumberFormatException.class) + public void givenBigIntegerConstructor_whenDecimalInInput_thenFail() { + BigInteger bigInteger = new BigInteger("4.0"); + } + + @Test(expected = NumberFormatException.class) + public void givenDecodeMethod_whenAlphabetInInput_thenFail() { + Long decodedLong = Long.decode("64403L"); + } + + /* ---INTEGER PASS CASES--- */ + @Test + public void givenInvalidNumberInputs_whenOptimized_thenPass() { + Byte byteInt = new Byte("1"); + assertEquals(1, byteInt.intValue()); + + Short shortInt = new Short("2 ".trim()); + assertEquals(2, shortInt.intValue()); + + Integer aIntObj = Integer.valueOf("6"); + assertEquals(6, aIntObj.intValue()); + + BigInteger bigInteger = new BigInteger("4"); + assertEquals(4, bigInteger.intValue()); + + int aIntPrim = Integer.parseInt("6000 ".trim()); + assertEquals(6000, aIntPrim); + + int bIntPrim = Integer.parseInt("_6000".replaceAll("_", "")); + assertEquals(6000, bIntPrim); + + int cIntPrim = Integer.parseInt("-6000"); + assertEquals(-6000, cIntPrim); + + Long decodeInteger = Long.decode("644032334"); + assertEquals(644032334L, decodeInteger.longValue()); + } + + /* ---DOUBLE FAIL CASES--- */ + @Test(expected = NumberFormatException.class) + public void givenFloatConstructor_whenAlphabetInInput_thenFail() { + Float floatDecimalObj = new Float("one.1"); + } + + @Test(expected = NumberFormatException.class) + public void givenDoubleConstructor_whenAlphabetInInput_thenFail() { + Double doubleDecimalObj = new Double("two.2"); + } + + @Test(expected = NumberFormatException.class) + public void givenBigDecimalConstructor_whenSpecialCharsInInput_thenFail() { + BigDecimal bigDecimalObj = new BigDecimal("3_0.3"); + } + + @Test(expected = NumberFormatException.class) + public void givenParseDoubleMethod_whenCommaInInput_thenFail() { + double aDoublePrim = Double.parseDouble("4000,1"); + } + + /* ---DOUBLE PASS CASES--- */ + @Test + public void givenDoubleConstructor_whenDecimalInInput_thenPass() { + Double doubleDecimalObj = new Double("2.2"); + assertEquals(2.2, doubleDecimalObj.doubleValue(), 0); + } + + @Test + public void givenDoubleValueOfMethod_whenMinusInInput_thenPass() { + Double aDoubleObj = Double.valueOf("-6000"); + assertEquals(-6000, aDoubleObj.doubleValue(), 0); + } + + @Test + public void givenUsDecimalNumber_whenParsedWithNumberFormat_thenPass() throws ParseException { + Number parsedNumber = parseNumberWithLocale("4000.1", Locale.US); + assertEquals(4000.1, parsedNumber); + assertEquals(4000.1, parsedNumber.doubleValue(), 0); + assertEquals(4000, parsedNumber.intValue()); + } + + /** + * In most European countries (for example, France), comma is used as decimal in place of period. + * @throws ParseException if the input string contains special characters other than comma or decimal. + * In this test case, anything after decimal (period) is dropped when a European locale is set. + */ + @Test + public void givenEuDecimalNumberHasComma_whenParsedWithNumberFormat_thenPass() throws ParseException { + Number parsedNumber = parseNumberWithLocale("4000,1", Locale.FRANCE); + LOG.info("Number parsed is: " + parsedNumber); + assertEquals(4000.1, parsedNumber); + assertEquals(4000.1, parsedNumber.doubleValue(), 0); + assertEquals(4000, parsedNumber.intValue()); + } + + /** + * Converts a string into a number retaining all decimals, and symbols valid in a locale. + * @param number the input string for a number. + * @param locale the locale to consider while parsing a number. + * @return the generic number object which can represent multiple number types. + * @throws ParseException when input contains invalid characters. + */ + private Number parseNumberWithLocale(String number, Locale locale) throws ParseException { + locale = locale == null ? Locale.getDefault() : locale; + NumberFormat numberFormat = NumberFormat.getInstance(locale); + return numberFormat.parse(number); + } + +} diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java new file mode 100644 index 0000000000..5d0f3b9c3e --- /dev/null +++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java @@ -0,0 +1,114 @@ +package com.baeldung.exceptions; + +import com.google.common.base.Throwables; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; + +import static com.baeldung.exceptions.RootCauseFinder.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests the {@link RootCauseFinder}. + */ +public class RootCauseFinderUnitTest { + + @Test + public void givenBirthDate_whenCalculatingAge_thenAgeReturned() { + try { + int age = AgeCalculator.calculateAge("1990-01-01"); + Assertions.assertEquals(1990, LocalDate + .now() + .minus(age, ChronoUnit.YEARS) + .getYear()); + } catch (CalculationException e) { + Assertions.fail(e.getMessage()); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof IllegalArgumentException); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseNotFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof IllegalArgumentException); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(Throwables.getRootCause(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(Throwables.getRootCause(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(Throwables.getRootCause(ex) instanceof IllegalArgumentException); + } + } + +} diff --git a/core-java-io/.gitignore b/core-java-modules/core-java-io/.gitignore similarity index 100% rename from core-java-io/.gitignore rename to core-java-modules/core-java-io/.gitignore diff --git a/core-java-io/README.md b/core-java-modules/core-java-io/README.md similarity index 71% rename from core-java-io/README.md rename to core-java-modules/core-java-io/README.md index 3d028783ed..6737ad6eb9 100644 --- a/core-java-io/README.md +++ b/core-java-modules/core-java-io/README.md @@ -3,18 +3,18 @@ ## 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) +- [Java – Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) - [Java Scanner](http://www.baeldung.com/java-scanner) - [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) +- [How to Copy a File with Java](http://www.baeldung.com/java-copy-file) - [Java – Append Data to a File](http://www.baeldung.com/java-append-to-file) - [FileNotFoundException in Java](http://www.baeldung.com/java-filenotfound-exception) - [How to Read a File in Java](http://www.baeldung.com/reading-file-in-java) @@ -30,8 +30,14 @@ - [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) - [Guide to BufferedReader](https://www.baeldung.com/java-buffered-reader) +- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension) +- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) +- [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) +- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector) diff --git a/core-java-modules/core-java-io/hard_link.txt b/core-java-modules/core-java-io/hard_link.txt new file mode 100644 index 0000000000..931a810b8d --- /dev/null +++ b/core-java-modules/core-java-io/hard_link.txt @@ -0,0 +1,10000 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 +4669 +4670 +4671 +4672 +4673 +4674 +4675 +4676 +4677 +4678 +4679 +4680 +4681 +4682 +4683 +4684 +4685 +4686 +4687 +4688 +4689 +4690 +4691 +4692 +4693 +4694 +4695 +4696 +4697 +4698 +4699 +4700 +4701 +4702 +4703 +4704 +4705 +4706 +4707 +4708 +4709 +4710 +4711 +4712 +4713 +4714 +4715 +4716 +4717 +4718 +4719 +4720 +4721 +4722 +4723 +4724 +4725 +4726 +4727 +4728 +4729 +4730 +4731 +4732 +4733 +4734 +4735 +4736 +4737 +4738 +4739 +4740 +4741 +4742 +4743 +4744 +4745 +4746 +4747 +4748 +4749 +4750 +4751 +4752 +4753 +4754 +4755 +4756 +4757 +4758 +4759 +4760 +4761 +4762 +4763 +4764 +4765 +4766 +4767 +4768 +4769 +4770 +4771 +4772 +4773 +4774 +4775 +4776 +4777 +4778 +4779 +4780 +4781 +4782 +4783 +4784 +4785 +4786 +4787 +4788 +4789 +4790 +4791 +4792 +4793 +4794 +4795 +4796 +4797 +4798 +4799 +4800 +4801 +4802 +4803 +4804 +4805 +4806 +4807 +4808 +4809 +4810 +4811 +4812 +4813 +4814 +4815 +4816 +4817 +4818 +4819 +4820 +4821 +4822 +4823 +4824 +4825 +4826 +4827 +4828 +4829 +4830 +4831 +4832 +4833 +4834 +4835 +4836 +4837 +4838 +4839 +4840 +4841 +4842 +4843 +4844 +4845 +4846 +4847 +4848 +4849 +4850 +4851 +4852 +4853 +4854 +4855 +4856 +4857 +4858 +4859 +4860 +4861 +4862 +4863 +4864 +4865 +4866 +4867 +4868 +4869 +4870 +4871 +4872 +4873 +4874 +4875 +4876 +4877 +4878 +4879 +4880 +4881 +4882 +4883 +4884 +4885 +4886 +4887 +4888 +4889 +4890 +4891 +4892 +4893 +4894 +4895 +4896 +4897 +4898 +4899 +4900 +4901 +4902 +4903 +4904 +4905 +4906 +4907 +4908 +4909 +4910 +4911 +4912 +4913 +4914 +4915 +4916 +4917 +4918 +4919 +4920 +4921 +4922 +4923 +4924 +4925 +4926 +4927 +4928 +4929 +4930 +4931 +4932 +4933 +4934 +4935 +4936 +4937 +4938 +4939 +4940 +4941 +4942 +4943 +4944 +4945 +4946 +4947 +4948 +4949 +4950 +4951 +4952 +4953 +4954 +4955 +4956 +4957 +4958 +4959 +4960 +4961 +4962 +4963 +4964 +4965 +4966 +4967 +4968 +4969 +4970 +4971 +4972 +4973 +4974 +4975 +4976 +4977 +4978 +4979 +4980 +4981 +4982 +4983 +4984 +4985 +4986 +4987 +4988 +4989 +4990 +4991 +4992 +4993 +4994 +4995 +4996 +4997 +4998 +4999 +5000 +5001 +5002 +5003 +5004 +5005 +5006 +5007 +5008 +5009 +5010 +5011 +5012 +5013 +5014 +5015 +5016 +5017 +5018 +5019 +5020 +5021 +5022 +5023 +5024 +5025 +5026 +5027 +5028 +5029 +5030 +5031 +5032 +5033 +5034 +5035 +5036 +5037 +5038 +5039 +5040 +5041 +5042 +5043 +5044 +5045 +5046 +5047 +5048 +5049 +5050 +5051 +5052 +5053 +5054 +5055 +5056 +5057 +5058 +5059 +5060 +5061 +5062 +5063 +5064 +5065 +5066 +5067 +5068 +5069 +5070 +5071 +5072 +5073 +5074 +5075 +5076 +5077 +5078 +5079 +5080 +5081 +5082 +5083 +5084 +5085 +5086 +5087 +5088 +5089 +5090 +5091 +5092 +5093 +5094 +5095 +5096 +5097 +5098 +5099 +5100 +5101 +5102 +5103 +5104 +5105 +5106 +5107 +5108 +5109 +5110 +5111 +5112 +5113 +5114 +5115 +5116 +5117 +5118 +5119 +5120 +5121 +5122 +5123 +5124 +5125 +5126 +5127 +5128 +5129 +5130 +5131 +5132 +5133 +5134 +5135 +5136 +5137 +5138 +5139 +5140 +5141 +5142 +5143 +5144 +5145 +5146 +5147 +5148 +5149 +5150 +5151 +5152 +5153 +5154 +5155 +5156 +5157 +5158 +5159 +5160 +5161 +5162 +5163 +5164 +5165 +5166 +5167 +5168 +5169 +5170 +5171 +5172 +5173 +5174 +5175 +5176 +5177 +5178 +5179 +5180 +5181 +5182 +5183 +5184 +5185 +5186 +5187 +5188 +5189 +5190 +5191 +5192 +5193 +5194 +5195 +5196 +5197 +5198 +5199 +5200 +5201 +5202 +5203 +5204 +5205 +5206 +5207 +5208 +5209 +5210 +5211 +5212 +5213 +5214 +5215 +5216 +5217 +5218 +5219 +5220 +5221 +5222 +5223 +5224 +5225 +5226 +5227 +5228 +5229 +5230 +5231 +5232 +5233 +5234 +5235 +5236 +5237 +5238 +5239 +5240 +5241 +5242 +5243 +5244 +5245 +5246 +5247 +5248 +5249 +5250 +5251 +5252 +5253 +5254 +5255 +5256 +5257 +5258 +5259 +5260 +5261 +5262 +5263 +5264 +5265 +5266 +5267 +5268 +5269 +5270 +5271 +5272 +5273 +5274 +5275 +5276 +5277 +5278 +5279 +5280 +5281 +5282 +5283 +5284 +5285 +5286 +5287 +5288 +5289 +5290 +5291 +5292 +5293 +5294 +5295 +5296 +5297 +5298 +5299 +5300 +5301 +5302 +5303 +5304 +5305 +5306 +5307 +5308 +5309 +5310 +5311 +5312 +5313 +5314 +5315 +5316 +5317 +5318 +5319 +5320 +5321 +5322 +5323 +5324 +5325 +5326 +5327 +5328 +5329 +5330 +5331 +5332 +5333 +5334 +5335 +5336 +5337 +5338 +5339 +5340 +5341 +5342 +5343 +5344 +5345 +5346 +5347 +5348 +5349 +5350 +5351 +5352 +5353 +5354 +5355 +5356 +5357 +5358 +5359 +5360 +5361 +5362 +5363 +5364 +5365 +5366 +5367 +5368 +5369 +5370 +5371 +5372 +5373 +5374 +5375 +5376 +5377 +5378 +5379 +5380 +5381 +5382 +5383 +5384 +5385 +5386 +5387 +5388 +5389 +5390 +5391 +5392 +5393 +5394 +5395 +5396 +5397 +5398 +5399 +5400 +5401 +5402 +5403 +5404 +5405 +5406 +5407 +5408 +5409 +5410 +5411 +5412 +5413 +5414 +5415 +5416 +5417 +5418 +5419 +5420 +5421 +5422 +5423 +5424 +5425 +5426 +5427 +5428 +5429 +5430 +5431 +5432 +5433 +5434 +5435 +5436 +5437 +5438 +5439 +5440 +5441 +5442 +5443 +5444 +5445 +5446 +5447 +5448 +5449 +5450 +5451 +5452 +5453 +5454 +5455 +5456 +5457 +5458 +5459 +5460 +5461 +5462 +5463 +5464 +5465 +5466 +5467 +5468 +5469 +5470 +5471 +5472 +5473 +5474 +5475 +5476 +5477 +5478 +5479 +5480 +5481 +5482 +5483 +5484 +5485 +5486 +5487 +5488 +5489 +5490 +5491 +5492 +5493 +5494 +5495 +5496 +5497 +5498 +5499 +5500 +5501 +5502 +5503 +5504 +5505 +5506 +5507 +5508 +5509 +5510 +5511 +5512 +5513 +5514 +5515 +5516 +5517 +5518 +5519 +5520 +5521 +5522 +5523 +5524 +5525 +5526 +5527 +5528 +5529 +5530 +5531 +5532 +5533 +5534 +5535 +5536 +5537 +5538 +5539 +5540 +5541 +5542 +5543 +5544 +5545 +5546 +5547 +5548 +5549 +5550 +5551 +5552 +5553 +5554 +5555 +5556 +5557 +5558 +5559 +5560 +5561 +5562 +5563 +5564 +5565 +5566 +5567 +5568 +5569 +5570 +5571 +5572 +5573 +5574 +5575 +5576 +5577 +5578 +5579 +5580 +5581 +5582 +5583 +5584 +5585 +5586 +5587 +5588 +5589 +5590 +5591 +5592 +5593 +5594 +5595 +5596 +5597 +5598 +5599 +5600 +5601 +5602 +5603 +5604 +5605 +5606 +5607 +5608 +5609 +5610 +5611 +5612 +5613 +5614 +5615 +5616 +5617 +5618 +5619 +5620 +5621 +5622 +5623 +5624 +5625 +5626 +5627 +5628 +5629 +5630 +5631 +5632 +5633 +5634 +5635 +5636 +5637 +5638 +5639 +5640 +5641 +5642 +5643 +5644 +5645 +5646 +5647 +5648 +5649 +5650 +5651 +5652 +5653 +5654 +5655 +5656 +5657 +5658 +5659 +5660 +5661 +5662 +5663 +5664 +5665 +5666 +5667 +5668 +5669 +5670 +5671 +5672 +5673 +5674 +5675 +5676 +5677 +5678 +5679 +5680 +5681 +5682 +5683 +5684 +5685 +5686 +5687 +5688 +5689 +5690 +5691 +5692 +5693 +5694 +5695 +5696 +5697 +5698 +5699 +5700 +5701 +5702 +5703 +5704 +5705 +5706 +5707 +5708 +5709 +5710 +5711 +5712 +5713 +5714 +5715 +5716 +5717 +5718 +5719 +5720 +5721 +5722 +5723 +5724 +5725 +5726 +5727 +5728 +5729 +5730 +5731 +5732 +5733 +5734 +5735 +5736 +5737 +5738 +5739 +5740 +5741 +5742 +5743 +5744 +5745 +5746 +5747 +5748 +5749 +5750 +5751 +5752 +5753 +5754 +5755 +5756 +5757 +5758 +5759 +5760 +5761 +5762 +5763 +5764 +5765 +5766 +5767 +5768 +5769 +5770 +5771 +5772 +5773 +5774 +5775 +5776 +5777 +5778 +5779 +5780 +5781 +5782 +5783 +5784 +5785 +5786 +5787 +5788 +5789 +5790 +5791 +5792 +5793 +5794 +5795 +5796 +5797 +5798 +5799 +5800 +5801 +5802 +5803 +5804 +5805 +5806 +5807 +5808 +5809 +5810 +5811 +5812 +5813 +5814 +5815 +5816 +5817 +5818 +5819 +5820 +5821 +5822 +5823 +5824 +5825 +5826 +5827 +5828 +5829 +5830 +5831 +5832 +5833 +5834 +5835 +5836 +5837 +5838 +5839 +5840 +5841 +5842 +5843 +5844 +5845 +5846 +5847 +5848 +5849 +5850 +5851 +5852 +5853 +5854 +5855 +5856 +5857 +5858 +5859 +5860 +5861 +5862 +5863 +5864 +5865 +5866 +5867 +5868 +5869 +5870 +5871 +5872 +5873 +5874 +5875 +5876 +5877 +5878 +5879 +5880 +5881 +5882 +5883 +5884 +5885 +5886 +5887 +5888 +5889 +5890 +5891 +5892 +5893 +5894 +5895 +5896 +5897 +5898 +5899 +5900 +5901 +5902 +5903 +5904 +5905 +5906 +5907 +5908 +5909 +5910 +5911 +5912 +5913 +5914 +5915 +5916 +5917 +5918 +5919 +5920 +5921 +5922 +5923 +5924 +5925 +5926 +5927 +5928 +5929 +5930 +5931 +5932 +5933 +5934 +5935 +5936 +5937 +5938 +5939 +5940 +5941 +5942 +5943 +5944 +5945 +5946 +5947 +5948 +5949 +5950 +5951 +5952 +5953 +5954 +5955 +5956 +5957 +5958 +5959 +5960 +5961 +5962 +5963 +5964 +5965 +5966 +5967 +5968 +5969 +5970 +5971 +5972 +5973 +5974 +5975 +5976 +5977 +5978 +5979 +5980 +5981 +5982 +5983 +5984 +5985 +5986 +5987 +5988 +5989 +5990 +5991 +5992 +5993 +5994 +5995 +5996 +5997 +5998 +5999 +6000 +6001 +6002 +6003 +6004 +6005 +6006 +6007 +6008 +6009 +6010 +6011 +6012 +6013 +6014 +6015 +6016 +6017 +6018 +6019 +6020 +6021 +6022 +6023 +6024 +6025 +6026 +6027 +6028 +6029 +6030 +6031 +6032 +6033 +6034 +6035 +6036 +6037 +6038 +6039 +6040 +6041 +6042 +6043 +6044 +6045 +6046 +6047 +6048 +6049 +6050 +6051 +6052 +6053 +6054 +6055 +6056 +6057 +6058 +6059 +6060 +6061 +6062 +6063 +6064 +6065 +6066 +6067 +6068 +6069 +6070 +6071 +6072 +6073 +6074 +6075 +6076 +6077 +6078 +6079 +6080 +6081 +6082 +6083 +6084 +6085 +6086 +6087 +6088 +6089 +6090 +6091 +6092 +6093 +6094 +6095 +6096 +6097 +6098 +6099 +6100 +6101 +6102 +6103 +6104 +6105 +6106 +6107 +6108 +6109 +6110 +6111 +6112 +6113 +6114 +6115 +6116 +6117 +6118 +6119 +6120 +6121 +6122 +6123 +6124 +6125 +6126 +6127 +6128 +6129 +6130 +6131 +6132 +6133 +6134 +6135 +6136 +6137 +6138 +6139 +6140 +6141 +6142 +6143 +6144 +6145 +6146 +6147 +6148 +6149 +6150 +6151 +6152 +6153 +6154 +6155 +6156 +6157 +6158 +6159 +6160 +6161 +6162 +6163 +6164 +6165 +6166 +6167 +6168 +6169 +6170 +6171 +6172 +6173 +6174 +6175 +6176 +6177 +6178 +6179 +6180 +6181 +6182 +6183 +6184 +6185 +6186 +6187 +6188 +6189 +6190 +6191 +6192 +6193 +6194 +6195 +6196 +6197 +6198 +6199 +6200 +6201 +6202 +6203 +6204 +6205 +6206 +6207 +6208 +6209 +6210 +6211 +6212 +6213 +6214 +6215 +6216 +6217 +6218 +6219 +6220 +6221 +6222 +6223 +6224 +6225 +6226 +6227 +6228 +6229 +6230 +6231 +6232 +6233 +6234 +6235 +6236 +6237 +6238 +6239 +6240 +6241 +6242 +6243 +6244 +6245 +6246 +6247 +6248 +6249 +6250 +6251 +6252 +6253 +6254 +6255 +6256 +6257 +6258 +6259 +6260 +6261 +6262 +6263 +6264 +6265 +6266 +6267 +6268 +6269 +6270 +6271 +6272 +6273 +6274 +6275 +6276 +6277 +6278 +6279 +6280 +6281 +6282 +6283 +6284 +6285 +6286 +6287 +6288 +6289 +6290 +6291 +6292 +6293 +6294 +6295 +6296 +6297 +6298 +6299 +6300 +6301 +6302 +6303 +6304 +6305 +6306 +6307 +6308 +6309 +6310 +6311 +6312 +6313 +6314 +6315 +6316 +6317 +6318 +6319 +6320 +6321 +6322 +6323 +6324 +6325 +6326 +6327 +6328 +6329 +6330 +6331 +6332 +6333 +6334 +6335 +6336 +6337 +6338 +6339 +6340 +6341 +6342 +6343 +6344 +6345 +6346 +6347 +6348 +6349 +6350 +6351 +6352 +6353 +6354 +6355 +6356 +6357 +6358 +6359 +6360 +6361 +6362 +6363 +6364 +6365 +6366 +6367 +6368 +6369 +6370 +6371 +6372 +6373 +6374 +6375 +6376 +6377 +6378 +6379 +6380 +6381 +6382 +6383 +6384 +6385 +6386 +6387 +6388 +6389 +6390 +6391 +6392 +6393 +6394 +6395 +6396 +6397 +6398 +6399 +6400 +6401 +6402 +6403 +6404 +6405 +6406 +6407 +6408 +6409 +6410 +6411 +6412 +6413 +6414 +6415 +6416 +6417 +6418 +6419 +6420 +6421 +6422 +6423 +6424 +6425 +6426 +6427 +6428 +6429 +6430 +6431 +6432 +6433 +6434 +6435 +6436 +6437 +6438 +6439 +6440 +6441 +6442 +6443 +6444 +6445 +6446 +6447 +6448 +6449 +6450 +6451 +6452 +6453 +6454 +6455 +6456 +6457 +6458 +6459 +6460 +6461 +6462 +6463 +6464 +6465 +6466 +6467 +6468 +6469 +6470 +6471 +6472 +6473 +6474 +6475 +6476 +6477 +6478 +6479 +6480 +6481 +6482 +6483 +6484 +6485 +6486 +6487 +6488 +6489 +6490 +6491 +6492 +6493 +6494 +6495 +6496 +6497 +6498 +6499 +6500 +6501 +6502 +6503 +6504 +6505 +6506 +6507 +6508 +6509 +6510 +6511 +6512 +6513 +6514 +6515 +6516 +6517 +6518 +6519 +6520 +6521 +6522 +6523 +6524 +6525 +6526 +6527 +6528 +6529 +6530 +6531 +6532 +6533 +6534 +6535 +6536 +6537 +6538 +6539 +6540 +6541 +6542 +6543 +6544 +6545 +6546 +6547 +6548 +6549 +6550 +6551 +6552 +6553 +6554 +6555 +6556 +6557 +6558 +6559 +6560 +6561 +6562 +6563 +6564 +6565 +6566 +6567 +6568 +6569 +6570 +6571 +6572 +6573 +6574 +6575 +6576 +6577 +6578 +6579 +6580 +6581 +6582 +6583 +6584 +6585 +6586 +6587 +6588 +6589 +6590 +6591 +6592 +6593 +6594 +6595 +6596 +6597 +6598 +6599 +6600 +6601 +6602 +6603 +6604 +6605 +6606 +6607 +6608 +6609 +6610 +6611 +6612 +6613 +6614 +6615 +6616 +6617 +6618 +6619 +6620 +6621 +6622 +6623 +6624 +6625 +6626 +6627 +6628 +6629 +6630 +6631 +6632 +6633 +6634 +6635 +6636 +6637 +6638 +6639 +6640 +6641 +6642 +6643 +6644 +6645 +6646 +6647 +6648 +6649 +6650 +6651 +6652 +6653 +6654 +6655 +6656 +6657 +6658 +6659 +6660 +6661 +6662 +6663 +6664 +6665 +6666 +6667 +6668 +6669 +6670 +6671 +6672 +6673 +6674 +6675 +6676 +6677 +6678 +6679 +6680 +6681 +6682 +6683 +6684 +6685 +6686 +6687 +6688 +6689 +6690 +6691 +6692 +6693 +6694 +6695 +6696 +6697 +6698 +6699 +6700 +6701 +6702 +6703 +6704 +6705 +6706 +6707 +6708 +6709 +6710 +6711 +6712 +6713 +6714 +6715 +6716 +6717 +6718 +6719 +6720 +6721 +6722 +6723 +6724 +6725 +6726 +6727 +6728 +6729 +6730 +6731 +6732 +6733 +6734 +6735 +6736 +6737 +6738 +6739 +6740 +6741 +6742 +6743 +6744 +6745 +6746 +6747 +6748 +6749 +6750 +6751 +6752 +6753 +6754 +6755 +6756 +6757 +6758 +6759 +6760 +6761 +6762 +6763 +6764 +6765 +6766 +6767 +6768 +6769 +6770 +6771 +6772 +6773 +6774 +6775 +6776 +6777 +6778 +6779 +6780 +6781 +6782 +6783 +6784 +6785 +6786 +6787 +6788 +6789 +6790 +6791 +6792 +6793 +6794 +6795 +6796 +6797 +6798 +6799 +6800 +6801 +6802 +6803 +6804 +6805 +6806 +6807 +6808 +6809 +6810 +6811 +6812 +6813 +6814 +6815 +6816 +6817 +6818 +6819 +6820 +6821 +6822 +6823 +6824 +6825 +6826 +6827 +6828 +6829 +6830 +6831 +6832 +6833 +6834 +6835 +6836 +6837 +6838 +6839 +6840 +6841 +6842 +6843 +6844 +6845 +6846 +6847 +6848 +6849 +6850 +6851 +6852 +6853 +6854 +6855 +6856 +6857 +6858 +6859 +6860 +6861 +6862 +6863 +6864 +6865 +6866 +6867 +6868 +6869 +6870 +6871 +6872 +6873 +6874 +6875 +6876 +6877 +6878 +6879 +6880 +6881 +6882 +6883 +6884 +6885 +6886 +6887 +6888 +6889 +6890 +6891 +6892 +6893 +6894 +6895 +6896 +6897 +6898 +6899 +6900 +6901 +6902 +6903 +6904 +6905 +6906 +6907 +6908 +6909 +6910 +6911 +6912 +6913 +6914 +6915 +6916 +6917 +6918 +6919 +6920 +6921 +6922 +6923 +6924 +6925 +6926 +6927 +6928 +6929 +6930 +6931 +6932 +6933 +6934 +6935 +6936 +6937 +6938 +6939 +6940 +6941 +6942 +6943 +6944 +6945 +6946 +6947 +6948 +6949 +6950 +6951 +6952 +6953 +6954 +6955 +6956 +6957 +6958 +6959 +6960 +6961 +6962 +6963 +6964 +6965 +6966 +6967 +6968 +6969 +6970 +6971 +6972 +6973 +6974 +6975 +6976 +6977 +6978 +6979 +6980 +6981 +6982 +6983 +6984 +6985 +6986 +6987 +6988 +6989 +6990 +6991 +6992 +6993 +6994 +6995 +6996 +6997 +6998 +6999 +7000 +7001 +7002 +7003 +7004 +7005 +7006 +7007 +7008 +7009 +7010 +7011 +7012 +7013 +7014 +7015 +7016 +7017 +7018 +7019 +7020 +7021 +7022 +7023 +7024 +7025 +7026 +7027 +7028 +7029 +7030 +7031 +7032 +7033 +7034 +7035 +7036 +7037 +7038 +7039 +7040 +7041 +7042 +7043 +7044 +7045 +7046 +7047 +7048 +7049 +7050 +7051 +7052 +7053 +7054 +7055 +7056 +7057 +7058 +7059 +7060 +7061 +7062 +7063 +7064 +7065 +7066 +7067 +7068 +7069 +7070 +7071 +7072 +7073 +7074 +7075 +7076 +7077 +7078 +7079 +7080 +7081 +7082 +7083 +7084 +7085 +7086 +7087 +7088 +7089 +7090 +7091 +7092 +7093 +7094 +7095 +7096 +7097 +7098 +7099 +7100 +7101 +7102 +7103 +7104 +7105 +7106 +7107 +7108 +7109 +7110 +7111 +7112 +7113 +7114 +7115 +7116 +7117 +7118 +7119 +7120 +7121 +7122 +7123 +7124 +7125 +7126 +7127 +7128 +7129 +7130 +7131 +7132 +7133 +7134 +7135 +7136 +7137 +7138 +7139 +7140 +7141 +7142 +7143 +7144 +7145 +7146 +7147 +7148 +7149 +7150 +7151 +7152 +7153 +7154 +7155 +7156 +7157 +7158 +7159 +7160 +7161 +7162 +7163 +7164 +7165 +7166 +7167 +7168 +7169 +7170 +7171 +7172 +7173 +7174 +7175 +7176 +7177 +7178 +7179 +7180 +7181 +7182 +7183 +7184 +7185 +7186 +7187 +7188 +7189 +7190 +7191 +7192 +7193 +7194 +7195 +7196 +7197 +7198 +7199 +7200 +7201 +7202 +7203 +7204 +7205 +7206 +7207 +7208 +7209 +7210 +7211 +7212 +7213 +7214 +7215 +7216 +7217 +7218 +7219 +7220 +7221 +7222 +7223 +7224 +7225 +7226 +7227 +7228 +7229 +7230 +7231 +7232 +7233 +7234 +7235 +7236 +7237 +7238 +7239 +7240 +7241 +7242 +7243 +7244 +7245 +7246 +7247 +7248 +7249 +7250 +7251 +7252 +7253 +7254 +7255 +7256 +7257 +7258 +7259 +7260 +7261 +7262 +7263 +7264 +7265 +7266 +7267 +7268 +7269 +7270 +7271 +7272 +7273 +7274 +7275 +7276 +7277 +7278 +7279 +7280 +7281 +7282 +7283 +7284 +7285 +7286 +7287 +7288 +7289 +7290 +7291 +7292 +7293 +7294 +7295 +7296 +7297 +7298 +7299 +7300 +7301 +7302 +7303 +7304 +7305 +7306 +7307 +7308 +7309 +7310 +7311 +7312 +7313 +7314 +7315 +7316 +7317 +7318 +7319 +7320 +7321 +7322 +7323 +7324 +7325 +7326 +7327 +7328 +7329 +7330 +7331 +7332 +7333 +7334 +7335 +7336 +7337 +7338 +7339 +7340 +7341 +7342 +7343 +7344 +7345 +7346 +7347 +7348 +7349 +7350 +7351 +7352 +7353 +7354 +7355 +7356 +7357 +7358 +7359 +7360 +7361 +7362 +7363 +7364 +7365 +7366 +7367 +7368 +7369 +7370 +7371 +7372 +7373 +7374 +7375 +7376 +7377 +7378 +7379 +7380 +7381 +7382 +7383 +7384 +7385 +7386 +7387 +7388 +7389 +7390 +7391 +7392 +7393 +7394 +7395 +7396 +7397 +7398 +7399 +7400 +7401 +7402 +7403 +7404 +7405 +7406 +7407 +7408 +7409 +7410 +7411 +7412 +7413 +7414 +7415 +7416 +7417 +7418 +7419 +7420 +7421 +7422 +7423 +7424 +7425 +7426 +7427 +7428 +7429 +7430 +7431 +7432 +7433 +7434 +7435 +7436 +7437 +7438 +7439 +7440 +7441 +7442 +7443 +7444 +7445 +7446 +7447 +7448 +7449 +7450 +7451 +7452 +7453 +7454 +7455 +7456 +7457 +7458 +7459 +7460 +7461 +7462 +7463 +7464 +7465 +7466 +7467 +7468 +7469 +7470 +7471 +7472 +7473 +7474 +7475 +7476 +7477 +7478 +7479 +7480 +7481 +7482 +7483 +7484 +7485 +7486 +7487 +7488 +7489 +7490 +7491 +7492 +7493 +7494 +7495 +7496 +7497 +7498 +7499 +7500 +7501 +7502 +7503 +7504 +7505 +7506 +7507 +7508 +7509 +7510 +7511 +7512 +7513 +7514 +7515 +7516 +7517 +7518 +7519 +7520 +7521 +7522 +7523 +7524 +7525 +7526 +7527 +7528 +7529 +7530 +7531 +7532 +7533 +7534 +7535 +7536 +7537 +7538 +7539 +7540 +7541 +7542 +7543 +7544 +7545 +7546 +7547 +7548 +7549 +7550 +7551 +7552 +7553 +7554 +7555 +7556 +7557 +7558 +7559 +7560 +7561 +7562 +7563 +7564 +7565 +7566 +7567 +7568 +7569 +7570 +7571 +7572 +7573 +7574 +7575 +7576 +7577 +7578 +7579 +7580 +7581 +7582 +7583 +7584 +7585 +7586 +7587 +7588 +7589 +7590 +7591 +7592 +7593 +7594 +7595 +7596 +7597 +7598 +7599 +7600 +7601 +7602 +7603 +7604 +7605 +7606 +7607 +7608 +7609 +7610 +7611 +7612 +7613 +7614 +7615 +7616 +7617 +7618 +7619 +7620 +7621 +7622 +7623 +7624 +7625 +7626 +7627 +7628 +7629 +7630 +7631 +7632 +7633 +7634 +7635 +7636 +7637 +7638 +7639 +7640 +7641 +7642 +7643 +7644 +7645 +7646 +7647 +7648 +7649 +7650 +7651 +7652 +7653 +7654 +7655 +7656 +7657 +7658 +7659 +7660 +7661 +7662 +7663 +7664 +7665 +7666 +7667 +7668 +7669 +7670 +7671 +7672 +7673 +7674 +7675 +7676 +7677 +7678 +7679 +7680 +7681 +7682 +7683 +7684 +7685 +7686 +7687 +7688 +7689 +7690 +7691 +7692 +7693 +7694 +7695 +7696 +7697 +7698 +7699 +7700 +7701 +7702 +7703 +7704 +7705 +7706 +7707 +7708 +7709 +7710 +7711 +7712 +7713 +7714 +7715 +7716 +7717 +7718 +7719 +7720 +7721 +7722 +7723 +7724 +7725 +7726 +7727 +7728 +7729 +7730 +7731 +7732 +7733 +7734 +7735 +7736 +7737 +7738 +7739 +7740 +7741 +7742 +7743 +7744 +7745 +7746 +7747 +7748 +7749 +7750 +7751 +7752 +7753 +7754 +7755 +7756 +7757 +7758 +7759 +7760 +7761 +7762 +7763 +7764 +7765 +7766 +7767 +7768 +7769 +7770 +7771 +7772 +7773 +7774 +7775 +7776 +7777 +7778 +7779 +7780 +7781 +7782 +7783 +7784 +7785 +7786 +7787 +7788 +7789 +7790 +7791 +7792 +7793 +7794 +7795 +7796 +7797 +7798 +7799 +7800 +7801 +7802 +7803 +7804 +7805 +7806 +7807 +7808 +7809 +7810 +7811 +7812 +7813 +7814 +7815 +7816 +7817 +7818 +7819 +7820 +7821 +7822 +7823 +7824 +7825 +7826 +7827 +7828 +7829 +7830 +7831 +7832 +7833 +7834 +7835 +7836 +7837 +7838 +7839 +7840 +7841 +7842 +7843 +7844 +7845 +7846 +7847 +7848 +7849 +7850 +7851 +7852 +7853 +7854 +7855 +7856 +7857 +7858 +7859 +7860 +7861 +7862 +7863 +7864 +7865 +7866 +7867 +7868 +7869 +7870 +7871 +7872 +7873 +7874 +7875 +7876 +7877 +7878 +7879 +7880 +7881 +7882 +7883 +7884 +7885 +7886 +7887 +7888 +7889 +7890 +7891 +7892 +7893 +7894 +7895 +7896 +7897 +7898 +7899 +7900 +7901 +7902 +7903 +7904 +7905 +7906 +7907 +7908 +7909 +7910 +7911 +7912 +7913 +7914 +7915 +7916 +7917 +7918 +7919 +7920 +7921 +7922 +7923 +7924 +7925 +7926 +7927 +7928 +7929 +7930 +7931 +7932 +7933 +7934 +7935 +7936 +7937 +7938 +7939 +7940 +7941 +7942 +7943 +7944 +7945 +7946 +7947 +7948 +7949 +7950 +7951 +7952 +7953 +7954 +7955 +7956 +7957 +7958 +7959 +7960 +7961 +7962 +7963 +7964 +7965 +7966 +7967 +7968 +7969 +7970 +7971 +7972 +7973 +7974 +7975 +7976 +7977 +7978 +7979 +7980 +7981 +7982 +7983 +7984 +7985 +7986 +7987 +7988 +7989 +7990 +7991 +7992 +7993 +7994 +7995 +7996 +7997 +7998 +7999 +8000 +8001 +8002 +8003 +8004 +8005 +8006 +8007 +8008 +8009 +8010 +8011 +8012 +8013 +8014 +8015 +8016 +8017 +8018 +8019 +8020 +8021 +8022 +8023 +8024 +8025 +8026 +8027 +8028 +8029 +8030 +8031 +8032 +8033 +8034 +8035 +8036 +8037 +8038 +8039 +8040 +8041 +8042 +8043 +8044 +8045 +8046 +8047 +8048 +8049 +8050 +8051 +8052 +8053 +8054 +8055 +8056 +8057 +8058 +8059 +8060 +8061 +8062 +8063 +8064 +8065 +8066 +8067 +8068 +8069 +8070 +8071 +8072 +8073 +8074 +8075 +8076 +8077 +8078 +8079 +8080 +8081 +8082 +8083 +8084 +8085 +8086 +8087 +8088 +8089 +8090 +8091 +8092 +8093 +8094 +8095 +8096 +8097 +8098 +8099 +8100 +8101 +8102 +8103 +8104 +8105 +8106 +8107 +8108 +8109 +8110 +8111 +8112 +8113 +8114 +8115 +8116 +8117 +8118 +8119 +8120 +8121 +8122 +8123 +8124 +8125 +8126 +8127 +8128 +8129 +8130 +8131 +8132 +8133 +8134 +8135 +8136 +8137 +8138 +8139 +8140 +8141 +8142 +8143 +8144 +8145 +8146 +8147 +8148 +8149 +8150 +8151 +8152 +8153 +8154 +8155 +8156 +8157 +8158 +8159 +8160 +8161 +8162 +8163 +8164 +8165 +8166 +8167 +8168 +8169 +8170 +8171 +8172 +8173 +8174 +8175 +8176 +8177 +8178 +8179 +8180 +8181 +8182 +8183 +8184 +8185 +8186 +8187 +8188 +8189 +8190 +8191 +8192 +8193 +8194 +8195 +8196 +8197 +8198 +8199 +8200 +8201 +8202 +8203 +8204 +8205 +8206 +8207 +8208 +8209 +8210 +8211 +8212 +8213 +8214 +8215 +8216 +8217 +8218 +8219 +8220 +8221 +8222 +8223 +8224 +8225 +8226 +8227 +8228 +8229 +8230 +8231 +8232 +8233 +8234 +8235 +8236 +8237 +8238 +8239 +8240 +8241 +8242 +8243 +8244 +8245 +8246 +8247 +8248 +8249 +8250 +8251 +8252 +8253 +8254 +8255 +8256 +8257 +8258 +8259 +8260 +8261 +8262 +8263 +8264 +8265 +8266 +8267 +8268 +8269 +8270 +8271 +8272 +8273 +8274 +8275 +8276 +8277 +8278 +8279 +8280 +8281 +8282 +8283 +8284 +8285 +8286 +8287 +8288 +8289 +8290 +8291 +8292 +8293 +8294 +8295 +8296 +8297 +8298 +8299 +8300 +8301 +8302 +8303 +8304 +8305 +8306 +8307 +8308 +8309 +8310 +8311 +8312 +8313 +8314 +8315 +8316 +8317 +8318 +8319 +8320 +8321 +8322 +8323 +8324 +8325 +8326 +8327 +8328 +8329 +8330 +8331 +8332 +8333 +8334 +8335 +8336 +8337 +8338 +8339 +8340 +8341 +8342 +8343 +8344 +8345 +8346 +8347 +8348 +8349 +8350 +8351 +8352 +8353 +8354 +8355 +8356 +8357 +8358 +8359 +8360 +8361 +8362 +8363 +8364 +8365 +8366 +8367 +8368 +8369 +8370 +8371 +8372 +8373 +8374 +8375 +8376 +8377 +8378 +8379 +8380 +8381 +8382 +8383 +8384 +8385 +8386 +8387 +8388 +8389 +8390 +8391 +8392 +8393 +8394 +8395 +8396 +8397 +8398 +8399 +8400 +8401 +8402 +8403 +8404 +8405 +8406 +8407 +8408 +8409 +8410 +8411 +8412 +8413 +8414 +8415 +8416 +8417 +8418 +8419 +8420 +8421 +8422 +8423 +8424 +8425 +8426 +8427 +8428 +8429 +8430 +8431 +8432 +8433 +8434 +8435 +8436 +8437 +8438 +8439 +8440 +8441 +8442 +8443 +8444 +8445 +8446 +8447 +8448 +8449 +8450 +8451 +8452 +8453 +8454 +8455 +8456 +8457 +8458 +8459 +8460 +8461 +8462 +8463 +8464 +8465 +8466 +8467 +8468 +8469 +8470 +8471 +8472 +8473 +8474 +8475 +8476 +8477 +8478 +8479 +8480 +8481 +8482 +8483 +8484 +8485 +8486 +8487 +8488 +8489 +8490 +8491 +8492 +8493 +8494 +8495 +8496 +8497 +8498 +8499 +8500 +8501 +8502 +8503 +8504 +8505 +8506 +8507 +8508 +8509 +8510 +8511 +8512 +8513 +8514 +8515 +8516 +8517 +8518 +8519 +8520 +8521 +8522 +8523 +8524 +8525 +8526 +8527 +8528 +8529 +8530 +8531 +8532 +8533 +8534 +8535 +8536 +8537 +8538 +8539 +8540 +8541 +8542 +8543 +8544 +8545 +8546 +8547 +8548 +8549 +8550 +8551 +8552 +8553 +8554 +8555 +8556 +8557 +8558 +8559 +8560 +8561 +8562 +8563 +8564 +8565 +8566 +8567 +8568 +8569 +8570 +8571 +8572 +8573 +8574 +8575 +8576 +8577 +8578 +8579 +8580 +8581 +8582 +8583 +8584 +8585 +8586 +8587 +8588 +8589 +8590 +8591 +8592 +8593 +8594 +8595 +8596 +8597 +8598 +8599 +8600 +8601 +8602 +8603 +8604 +8605 +8606 +8607 +8608 +8609 +8610 +8611 +8612 +8613 +8614 +8615 +8616 +8617 +8618 +8619 +8620 +8621 +8622 +8623 +8624 +8625 +8626 +8627 +8628 +8629 +8630 +8631 +8632 +8633 +8634 +8635 +8636 +8637 +8638 +8639 +8640 +8641 +8642 +8643 +8644 +8645 +8646 +8647 +8648 +8649 +8650 +8651 +8652 +8653 +8654 +8655 +8656 +8657 +8658 +8659 +8660 +8661 +8662 +8663 +8664 +8665 +8666 +8667 +8668 +8669 +8670 +8671 +8672 +8673 +8674 +8675 +8676 +8677 +8678 +8679 +8680 +8681 +8682 +8683 +8684 +8685 +8686 +8687 +8688 +8689 +8690 +8691 +8692 +8693 +8694 +8695 +8696 +8697 +8698 +8699 +8700 +8701 +8702 +8703 +8704 +8705 +8706 +8707 +8708 +8709 +8710 +8711 +8712 +8713 +8714 +8715 +8716 +8717 +8718 +8719 +8720 +8721 +8722 +8723 +8724 +8725 +8726 +8727 +8728 +8729 +8730 +8731 +8732 +8733 +8734 +8735 +8736 +8737 +8738 +8739 +8740 +8741 +8742 +8743 +8744 +8745 +8746 +8747 +8748 +8749 +8750 +8751 +8752 +8753 +8754 +8755 +8756 +8757 +8758 +8759 +8760 +8761 +8762 +8763 +8764 +8765 +8766 +8767 +8768 +8769 +8770 +8771 +8772 +8773 +8774 +8775 +8776 +8777 +8778 +8779 +8780 +8781 +8782 +8783 +8784 +8785 +8786 +8787 +8788 +8789 +8790 +8791 +8792 +8793 +8794 +8795 +8796 +8797 +8798 +8799 +8800 +8801 +8802 +8803 +8804 +8805 +8806 +8807 +8808 +8809 +8810 +8811 +8812 +8813 +8814 +8815 +8816 +8817 +8818 +8819 +8820 +8821 +8822 +8823 +8824 +8825 +8826 +8827 +8828 +8829 +8830 +8831 +8832 +8833 +8834 +8835 +8836 +8837 +8838 +8839 +8840 +8841 +8842 +8843 +8844 +8845 +8846 +8847 +8848 +8849 +8850 +8851 +8852 +8853 +8854 +8855 +8856 +8857 +8858 +8859 +8860 +8861 +8862 +8863 +8864 +8865 +8866 +8867 +8868 +8869 +8870 +8871 +8872 +8873 +8874 +8875 +8876 +8877 +8878 +8879 +8880 +8881 +8882 +8883 +8884 +8885 +8886 +8887 +8888 +8889 +8890 +8891 +8892 +8893 +8894 +8895 +8896 +8897 +8898 +8899 +8900 +8901 +8902 +8903 +8904 +8905 +8906 +8907 +8908 +8909 +8910 +8911 +8912 +8913 +8914 +8915 +8916 +8917 +8918 +8919 +8920 +8921 +8922 +8923 +8924 +8925 +8926 +8927 +8928 +8929 +8930 +8931 +8932 +8933 +8934 +8935 +8936 +8937 +8938 +8939 +8940 +8941 +8942 +8943 +8944 +8945 +8946 +8947 +8948 +8949 +8950 +8951 +8952 +8953 +8954 +8955 +8956 +8957 +8958 +8959 +8960 +8961 +8962 +8963 +8964 +8965 +8966 +8967 +8968 +8969 +8970 +8971 +8972 +8973 +8974 +8975 +8976 +8977 +8978 +8979 +8980 +8981 +8982 +8983 +8984 +8985 +8986 +8987 +8988 +8989 +8990 +8991 +8992 +8993 +8994 +8995 +8996 +8997 +8998 +8999 +9000 +9001 +9002 +9003 +9004 +9005 +9006 +9007 +9008 +9009 +9010 +9011 +9012 +9013 +9014 +9015 +9016 +9017 +9018 +9019 +9020 +9021 +9022 +9023 +9024 +9025 +9026 +9027 +9028 +9029 +9030 +9031 +9032 +9033 +9034 +9035 +9036 +9037 +9038 +9039 +9040 +9041 +9042 +9043 +9044 +9045 +9046 +9047 +9048 +9049 +9050 +9051 +9052 +9053 +9054 +9055 +9056 +9057 +9058 +9059 +9060 +9061 +9062 +9063 +9064 +9065 +9066 +9067 +9068 +9069 +9070 +9071 +9072 +9073 +9074 +9075 +9076 +9077 +9078 +9079 +9080 +9081 +9082 +9083 +9084 +9085 +9086 +9087 +9088 +9089 +9090 +9091 +9092 +9093 +9094 +9095 +9096 +9097 +9098 +9099 +9100 +9101 +9102 +9103 +9104 +9105 +9106 +9107 +9108 +9109 +9110 +9111 +9112 +9113 +9114 +9115 +9116 +9117 +9118 +9119 +9120 +9121 +9122 +9123 +9124 +9125 +9126 +9127 +9128 +9129 +9130 +9131 +9132 +9133 +9134 +9135 +9136 +9137 +9138 +9139 +9140 +9141 +9142 +9143 +9144 +9145 +9146 +9147 +9148 +9149 +9150 +9151 +9152 +9153 +9154 +9155 +9156 +9157 +9158 +9159 +9160 +9161 +9162 +9163 +9164 +9165 +9166 +9167 +9168 +9169 +9170 +9171 +9172 +9173 +9174 +9175 +9176 +9177 +9178 +9179 +9180 +9181 +9182 +9183 +9184 +9185 +9186 +9187 +9188 +9189 +9190 +9191 +9192 +9193 +9194 +9195 +9196 +9197 +9198 +9199 +9200 +9201 +9202 +9203 +9204 +9205 +9206 +9207 +9208 +9209 +9210 +9211 +9212 +9213 +9214 +9215 +9216 +9217 +9218 +9219 +9220 +9221 +9222 +9223 +9224 +9225 +9226 +9227 +9228 +9229 +9230 +9231 +9232 +9233 +9234 +9235 +9236 +9237 +9238 +9239 +9240 +9241 +9242 +9243 +9244 +9245 +9246 +9247 +9248 +9249 +9250 +9251 +9252 +9253 +9254 +9255 +9256 +9257 +9258 +9259 +9260 +9261 +9262 +9263 +9264 +9265 +9266 +9267 +9268 +9269 +9270 +9271 +9272 +9273 +9274 +9275 +9276 +9277 +9278 +9279 +9280 +9281 +9282 +9283 +9284 +9285 +9286 +9287 +9288 +9289 +9290 +9291 +9292 +9293 +9294 +9295 +9296 +9297 +9298 +9299 +9300 +9301 +9302 +9303 +9304 +9305 +9306 +9307 +9308 +9309 +9310 +9311 +9312 +9313 +9314 +9315 +9316 +9317 +9318 +9319 +9320 +9321 +9322 +9323 +9324 +9325 +9326 +9327 +9328 +9329 +9330 +9331 +9332 +9333 +9334 +9335 +9336 +9337 +9338 +9339 +9340 +9341 +9342 +9343 +9344 +9345 +9346 +9347 +9348 +9349 +9350 +9351 +9352 +9353 +9354 +9355 +9356 +9357 +9358 +9359 +9360 +9361 +9362 +9363 +9364 +9365 +9366 +9367 +9368 +9369 +9370 +9371 +9372 +9373 +9374 +9375 +9376 +9377 +9378 +9379 +9380 +9381 +9382 +9383 +9384 +9385 +9386 +9387 +9388 +9389 +9390 +9391 +9392 +9393 +9394 +9395 +9396 +9397 +9398 +9399 +9400 +9401 +9402 +9403 +9404 +9405 +9406 +9407 +9408 +9409 +9410 +9411 +9412 +9413 +9414 +9415 +9416 +9417 +9418 +9419 +9420 +9421 +9422 +9423 +9424 +9425 +9426 +9427 +9428 +9429 +9430 +9431 +9432 +9433 +9434 +9435 +9436 +9437 +9438 +9439 +9440 +9441 +9442 +9443 +9444 +9445 +9446 +9447 +9448 +9449 +9450 +9451 +9452 +9453 +9454 +9455 +9456 +9457 +9458 +9459 +9460 +9461 +9462 +9463 +9464 +9465 +9466 +9467 +9468 +9469 +9470 +9471 +9472 +9473 +9474 +9475 +9476 +9477 +9478 +9479 +9480 +9481 +9482 +9483 +9484 +9485 +9486 +9487 +9488 +9489 +9490 +9491 +9492 +9493 +9494 +9495 +9496 +9497 +9498 +9499 +9500 +9501 +9502 +9503 +9504 +9505 +9506 +9507 +9508 +9509 +9510 +9511 +9512 +9513 +9514 +9515 +9516 +9517 +9518 +9519 +9520 +9521 +9522 +9523 +9524 +9525 +9526 +9527 +9528 +9529 +9530 +9531 +9532 +9533 +9534 +9535 +9536 +9537 +9538 +9539 +9540 +9541 +9542 +9543 +9544 +9545 +9546 +9547 +9548 +9549 +9550 +9551 +9552 +9553 +9554 +9555 +9556 +9557 +9558 +9559 +9560 +9561 +9562 +9563 +9564 +9565 +9566 +9567 +9568 +9569 +9570 +9571 +9572 +9573 +9574 +9575 +9576 +9577 +9578 +9579 +9580 +9581 +9582 +9583 +9584 +9585 +9586 +9587 +9588 +9589 +9590 +9591 +9592 +9593 +9594 +9595 +9596 +9597 +9598 +9599 +9600 +9601 +9602 +9603 +9604 +9605 +9606 +9607 +9608 +9609 +9610 +9611 +9612 +9613 +9614 +9615 +9616 +9617 +9618 +9619 +9620 +9621 +9622 +9623 +9624 +9625 +9626 +9627 +9628 +9629 +9630 +9631 +9632 +9633 +9634 +9635 +9636 +9637 +9638 +9639 +9640 +9641 +9642 +9643 +9644 +9645 +9646 +9647 +9648 +9649 +9650 +9651 +9652 +9653 +9654 +9655 +9656 +9657 +9658 +9659 +9660 +9661 +9662 +9663 +9664 +9665 +9666 +9667 +9668 +9669 +9670 +9671 +9672 +9673 +9674 +9675 +9676 +9677 +9678 +9679 +9680 +9681 +9682 +9683 +9684 +9685 +9686 +9687 +9688 +9689 +9690 +9691 +9692 +9693 +9694 +9695 +9696 +9697 +9698 +9699 +9700 +9701 +9702 +9703 +9704 +9705 +9706 +9707 +9708 +9709 +9710 +9711 +9712 +9713 +9714 +9715 +9716 +9717 +9718 +9719 +9720 +9721 +9722 +9723 +9724 +9725 +9726 +9727 +9728 +9729 +9730 +9731 +9732 +9733 +9734 +9735 +9736 +9737 +9738 +9739 +9740 +9741 +9742 +9743 +9744 +9745 +9746 +9747 +9748 +9749 +9750 +9751 +9752 +9753 +9754 +9755 +9756 +9757 +9758 +9759 +9760 +9761 +9762 +9763 +9764 +9765 +9766 +9767 +9768 +9769 +9770 +9771 +9772 +9773 +9774 +9775 +9776 +9777 +9778 +9779 +9780 +9781 +9782 +9783 +9784 +9785 +9786 +9787 +9788 +9789 +9790 +9791 +9792 +9793 +9794 +9795 +9796 +9797 +9798 +9799 +9800 +9801 +9802 +9803 +9804 +9805 +9806 +9807 +9808 +9809 +9810 +9811 +9812 +9813 +9814 +9815 +9816 +9817 +9818 +9819 +9820 +9821 +9822 +9823 +9824 +9825 +9826 +9827 +9828 +9829 +9830 +9831 +9832 +9833 +9834 +9835 +9836 +9837 +9838 +9839 +9840 +9841 +9842 +9843 +9844 +9845 +9846 +9847 +9848 +9849 +9850 +9851 +9852 +9853 +9854 +9855 +9856 +9857 +9858 +9859 +9860 +9861 +9862 +9863 +9864 +9865 +9866 +9867 +9868 +9869 +9870 +9871 +9872 +9873 +9874 +9875 +9876 +9877 +9878 +9879 +9880 +9881 +9882 +9883 +9884 +9885 +9886 +9887 +9888 +9889 +9890 +9891 +9892 +9893 +9894 +9895 +9896 +9897 +9898 +9899 +9900 +9901 +9902 +9903 +9904 +9905 +9906 +9907 +9908 +9909 +9910 +9911 +9912 +9913 +9914 +9915 +9916 +9917 +9918 +9919 +9920 +9921 +9922 +9923 +9924 +9925 +9926 +9927 +9928 +9929 +9930 +9931 +9932 +9933 +9934 +9935 +9936 +9937 +9938 +9939 +9940 +9941 +9942 +9943 +9944 +9945 +9946 +9947 +9948 +9949 +9950 +9951 +9952 +9953 +9954 +9955 +9956 +9957 +9958 +9959 +9960 +9961 +9962 +9963 +9964 +9965 +9966 +9967 +9968 +9969 +9970 +9971 +9972 +9973 +9974 +9975 +9976 +9977 +9978 +9979 +9980 +9981 +9982 +9983 +9984 +9985 +9986 +9987 +9988 +9989 +9990 +9991 +9992 +9993 +9994 +9995 +9996 +9997 +9998 +9999 diff --git a/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml similarity index 94% rename from core-java-io/pom.xml rename to core-java-modules/core-java-io/pom.xml index efa32b8e3e..44c703ee68 100644 --- a/core-java-io/pom.xml +++ b/core-java-modules/core-java-io/pom.xml @@ -3,14 +3,14 @@ 4.0.0 core-java-io 0.1.0-SNAPSHOT - jar core-java-io + jar com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java @@ -160,6 +160,17 @@ ${opencsv.version} test + + + org.apache.tika + tika-core + ${tika.version} + + + net.sf.jmimemagic + jmimemagic + ${jmime-magic.version} + @@ -235,8 +246,6 @@ - - 2.8.5 3.5 @@ -248,7 +257,6 @@ 4.01 0.4 1.8.7 - 1.16.12 4.6-b01 1.13 0.6.5 @@ -264,6 +272,9 @@ 2.1.0.1 1.19 2.4.5 + + 1.18 + 0.1.5 \ No newline at end of file diff --git a/core-java-io/src/main/java/com/baeldung/bufferedreader/BufferedReaderExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/bufferedreader/BufferedReaderExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/bufferedreader/BufferedReaderExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/bufferedreader/BufferedReaderExample.java diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java new file mode 100644 index 0000000000..f409d05b06 --- /dev/null +++ b/core-java-modules/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java @@ -0,0 +1,22 @@ +package com.baeldung.csv; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class WriteCsvFileExample { + + public String convertToCSV(String[] data) { + return Stream.of(data) + .map(this::escapeSpecialCharacters) + .collect(Collectors.joining(",")); + } + + public String escapeSpecialCharacters(String data) { + String escapedData = data.replaceAll("\\R", " "); + if (data.contains(",") || data.contains("\"") || data.contains("'")) { + data = data.replace("\"", "\"\""); + escapedData = "\"" + data + "\""; + } + return escapedData; + } +} diff --git a/core-java-io/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/dirmonitoring/DirectoryMonitoringExample.java diff --git a/core-java-io/src/main/java/com/baeldung/download/FileDownload.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/download/FileDownload.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/download/FileDownload.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/download/FileDownload.java diff --git a/core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/download/ResumableDownload.java diff --git a/core-java/src/main/java/com/baeldung/extension/Extension.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/extension/Extension.java similarity index 100% rename from core-java/src/main/java/com/baeldung/extension/Extension.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/extension/Extension.java diff --git a/core-java-io/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java diff --git a/core-java-io/src/main/java/com/baeldung/fileparser/FileReaderExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/FileReaderExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/fileparser/FileReaderExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/FileReaderExample.java diff --git a/core-java-io/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java diff --git a/core-java-io/src/main/java/com/baeldung/fileparser/ScannerIntExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/ScannerIntExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/fileparser/ScannerIntExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/ScannerIntExample.java diff --git a/core-java-io/src/main/java/com/baeldung/fileparser/ScannerStringExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/ScannerStringExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/fileparser/ScannerStringExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/fileparser/ScannerStringExample.java diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/files/ListFiles.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/files/ListFiles.java new file mode 100644 index 0000000000..c5de36270c --- /dev/null +++ b/core-java-modules/core-java-io/src/main/java/com/baeldung/files/ListFiles.java @@ -0,0 +1,64 @@ +package com.baeldung.files; + +import java.io.File; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ListFiles { + public static final int DEPTH = 1; + + public Set listFilesUsingJavaIO(String dir) { + return Stream.of(new File(dir).listFiles()) + .filter(file -> !file.isDirectory()) + .map(File::getName) + .collect(Collectors.toSet()); + } + + public Set listFilesUsingFileWalk(String dir, int depth) throws IOException { + try (Stream stream = Files.walk(Paths.get(dir), depth)) { + return stream.filter(file -> !Files.isDirectory(file)) + .map(Path::getFileName) + .map(Path::toString) + .collect(Collectors.toSet()); + } + } + + public Set listFilesUsingFileWalkAndVisitor(String dir) throws IOException { + Set fileList = new HashSet<>(); + Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (!Files.isDirectory(file)) { + fileList.add(file.getFileName() + .toString()); + } + return FileVisitResult.CONTINUE; + } + }); + return fileList; + } + + public Set listFilesUsingDirectoryStream(String dir) throws IOException { + Set fileList = new HashSet<>(); + try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(dir))) { + for (Path path : stream) { + if (!Files.isDirectory(path)) { + fileList.add(path.getFileName() + .toString()); + } + } + } + return fileList; + } + +} diff --git a/core-java-io/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java diff --git a/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoClient.java diff --git a/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/EchoServer.java diff --git a/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio/selector/README.md diff --git a/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileSearchExample.java diff --git a/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/visitor/FileVisitorImpl.java diff --git a/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/java/nio2/watcher/DirectoryWatcherExample.java diff --git a/core-java-io/src/main/java/com/baeldung/stream/FileCopy.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/stream/FileCopy.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/stream/FileCopy.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/stream/FileCopy.java diff --git a/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java diff --git a/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/symlink/SymLinkExample.java diff --git a/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java diff --git a/core-java-io/src/main/java/com/baeldung/util/StreamUtils.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/util/StreamUtils.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/util/StreamUtils.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/util/StreamUtils.java diff --git a/core-java-io/src/main/java/com/baeldung/zip/ZipDirectory.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipDirectory.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/zip/ZipDirectory.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipDirectory.java diff --git a/core-java-io/src/main/java/com/baeldung/zip/ZipFile.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipFile.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/zip/ZipFile.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipFile.java diff --git a/core-java-io/src/main/java/com/baeldung/zip/ZipMultipleFiles.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipMultipleFiles.java similarity index 100% rename from core-java-io/src/main/java/com/baeldung/zip/ZipMultipleFiles.java rename to core-java-modules/core-java-io/src/main/java/com/baeldung/zip/ZipMultipleFiles.java diff --git a/core-java-io/src/main/resources/ESAPI.properties b/core-java-modules/core-java-io/src/main/resources/ESAPI.properties similarity index 100% rename from core-java-io/src/main/resources/ESAPI.properties rename to core-java-modules/core-java-io/src/main/resources/ESAPI.properties diff --git a/core-java/src/main/resources/META-INF/BenchmarkList b/core-java-modules/core-java-io/src/main/resources/META-INF/BenchmarkList old mode 100755 new mode 100644 similarity index 100% rename from core-java/src/main/resources/META-INF/BenchmarkList rename to core-java-modules/core-java-io/src/main/resources/META-INF/BenchmarkList diff --git a/core-java-io/src/main/resources/META-INF/persistence.xml b/core-java-modules/core-java-io/src/main/resources/META-INF/persistence.xml similarity index 100% rename from core-java-io/src/main/resources/META-INF/persistence.xml rename to core-java-modules/core-java-io/src/main/resources/META-INF/persistence.xml diff --git a/core-java-io/src/main/resources/META-INF/services/com.sun.source.util.Plugin b/core-java-modules/core-java-io/src/main/resources/META-INF/services/com.sun.source.util.Plugin similarity index 100% rename from core-java-io/src/main/resources/META-INF/services/com.sun.source.util.Plugin rename to core-java-modules/core-java-io/src/main/resources/META-INF/services/com.sun.source.util.Plugin diff --git a/core-java-io/src/main/resources/countries.properties b/core-java-modules/core-java-io/src/main/resources/countries.properties similarity index 82% rename from core-java-io/src/main/resources/countries.properties rename to core-java-modules/core-java-io/src/main/resources/countries.properties index e743b5a40b..3c1f53aded 100644 --- a/core-java-io/src/main/resources/countries.properties +++ b/core-java-modules/core-java-io/src/main/resources/countries.properties @@ -1,3 +1,3 @@ -UK -US -Germany +UK +US +Germany diff --git a/core-java-io/src/main/resources/data.csv b/core-java-modules/core-java-io/src/main/resources/data.csv similarity index 100% rename from core-java-io/src/main/resources/data.csv rename to core-java-modules/core-java-io/src/main/resources/data.csv diff --git a/core-java-io/src/main/resources/datasource.properties b/core-java-modules/core-java-io/src/main/resources/datasource.properties similarity index 100% rename from core-java-io/src/main/resources/datasource.properties rename to core-java-modules/core-java-io/src/main/resources/datasource.properties diff --git a/core-java-io/src/main/resources/dirCompressed.zip b/core-java-modules/core-java-io/src/main/resources/dirCompressed.zip similarity index 100% rename from core-java-io/src/main/resources/dirCompressed.zip rename to core-java-modules/core-java-io/src/main/resources/dirCompressed.zip diff --git a/core-java-io/src/main/resources/input.txt b/core-java-modules/core-java-io/src/main/resources/input.txt similarity index 100% rename from core-java-io/src/main/resources/input.txt rename to core-java-modules/core-java-io/src/main/resources/input.txt diff --git a/core-java-io/src/main/resources/js/bind.js b/core-java-modules/core-java-io/src/main/resources/js/bind.js similarity index 100% rename from core-java-io/src/main/resources/js/bind.js rename to core-java-modules/core-java-io/src/main/resources/js/bind.js diff --git a/core-java-io/src/main/resources/js/locations.js b/core-java-modules/core-java-io/src/main/resources/js/locations.js similarity index 100% rename from core-java-io/src/main/resources/js/locations.js rename to core-java-modules/core-java-io/src/main/resources/js/locations.js diff --git a/core-java-io/src/main/resources/js/math_module.js b/core-java-modules/core-java-io/src/main/resources/js/math_module.js similarity index 100% rename from core-java-io/src/main/resources/js/math_module.js rename to core-java-modules/core-java-io/src/main/resources/js/math_module.js diff --git a/core-java-io/src/main/resources/js/no_such.js b/core-java-modules/core-java-io/src/main/resources/js/no_such.js similarity index 100% rename from core-java-io/src/main/resources/js/no_such.js rename to core-java-modules/core-java-io/src/main/resources/js/no_such.js diff --git a/core-java-io/src/main/resources/js/script.js b/core-java-modules/core-java-io/src/main/resources/js/script.js similarity index 100% rename from core-java-io/src/main/resources/js/script.js rename to core-java-modules/core-java-io/src/main/resources/js/script.js diff --git a/core-java-io/src/main/resources/js/trim.js b/core-java-modules/core-java-io/src/main/resources/js/trim.js similarity index 100% rename from core-java-io/src/main/resources/js/trim.js rename to core-java-modules/core-java-io/src/main/resources/js/trim.js diff --git a/core-java-io/src/main/resources/js/typed_arrays.js b/core-java-modules/core-java-io/src/main/resources/js/typed_arrays.js similarity index 100% rename from core-java-io/src/main/resources/js/typed_arrays.js rename to core-java-modules/core-java-io/src/main/resources/js/typed_arrays.js diff --git a/core-java-io/src/main/resources/log4j.properties b/core-java-modules/core-java-io/src/main/resources/log4j.properties similarity index 100% rename from core-java-io/src/main/resources/log4j.properties rename to core-java-modules/core-java-io/src/main/resources/log4j.properties diff --git a/core-java-io/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties similarity index 100% rename from core-java-io/src/main/resources/log4jstructuraldp.properties rename to core-java-modules/core-java-io/src/main/resources/log4jstructuraldp.properties diff --git a/core-java-sun/src/main/resources/logback.xml b/core-java-modules/core-java-io/src/main/resources/logback.xml similarity index 100% rename from core-java-sun/src/main/resources/logback.xml rename to core-java-modules/core-java-io/src/main/resources/logback.xml diff --git a/core-java-io/src/main/resources/multiCompressed.zip b/core-java-modules/core-java-io/src/main/resources/multiCompressed.zip similarity index 100% rename from core-java-io/src/main/resources/multiCompressed.zip rename to core-java-modules/core-java-io/src/main/resources/multiCompressed.zip diff --git a/core-java-io/src/main/resources/unzipTest/compressed.zip b/core-java-modules/core-java-io/src/main/resources/unzipTest/compressed.zip similarity index 100% rename from core-java-io/src/main/resources/unzipTest/compressed.zip rename to core-java-modules/core-java-io/src/main/resources/unzipTest/compressed.zip diff --git a/core-java-io/src/main/resources/zipTest/test1.txt b/core-java-modules/core-java-io/src/main/resources/zipTest/test1.txt similarity index 100% rename from core-java-io/src/main/resources/zipTest/test1.txt rename to core-java-modules/core-java-io/src/main/resources/zipTest/test1.txt diff --git a/core-java-io/src/main/resources/zipTest/test2.txt b/core-java-modules/core-java-io/src/main/resources/zipTest/test2.txt similarity index 100% rename from core-java-io/src/main/resources/zipTest/test2.txt rename to core-java-modules/core-java-io/src/main/resources/zipTest/test2.txt diff --git a/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderExampleUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderExampleUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderExampleUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderExampleUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/bufferedreader/BufferedReaderUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java similarity index 97% rename from core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java index 4603644bf5..2b4a15ed59 100644 --- a/core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/copyfiles/FileCopierIntegrationTest.java @@ -1,69 +1,69 @@ -package com.baeldung.copyfiles; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; - -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Test; -import static org.assertj.core.api.Assertions.*; - -public class FileCopierIntegrationTest { - File original = new File("src/test/resources/original.txt"); - - @Before - public void init() throws IOException { - if (!original.exists()) - Files.createFile(original.toPath()); - } - - @Test - public void givenIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { - File copied = new File("src/test/resources/copiedWithIo.txt"); - try (InputStream in = new BufferedInputStream(new FileInputStream(original)); OutputStream out = new BufferedOutputStream(new FileOutputStream(copied))) { - byte[] buffer = new byte[1024]; - int lengthRead; - while ((lengthRead = in.read(buffer)) > 0) { - out.write(buffer, 0, lengthRead); - out.flush(); - } - } - assertThat(copied).exists(); - assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); - } - - @Test - public void givenCommonsIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { - File copied = new File("src/test/resources/copiedWithApacheCommons.txt"); - FileUtils.copyFile(original, copied); - assertThat(copied).exists(); - assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); - } - - @Test - public void givenNIO2_whenCopied_thenCopyExistsWithSameContents() throws IOException { - Path copied = Paths.get("src/test/resources/copiedWithNio.txt"); - Path originalPath = original.toPath(); - Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING); - assertThat(copied).exists(); - assertThat(Files.readAllLines(originalPath).equals(Files.readAllLines(copied))); - } - - @Test - public void givenGuava_whenCopied_thenCopyExistsWithSameContents() throws IOException { - File copied = new File("src/test/resources/copiedWithApacheCommons.txt"); - com.google.common.io.Files.copy(original, copied); - assertThat(copied).exists(); - assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); - } -} +package com.baeldung.copyfiles; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Test; +import static org.assertj.core.api.Assertions.*; + +public class FileCopierIntegrationTest { + File original = new File("src/test/resources/original.txt"); + + @Before + public void init() throws IOException { + if (!original.exists()) + Files.createFile(original.toPath()); + } + + @Test + public void givenIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { + File copied = new File("src/test/resources/copiedWithIo.txt"); + try (InputStream in = new BufferedInputStream(new FileInputStream(original)); OutputStream out = new BufferedOutputStream(new FileOutputStream(copied))) { + byte[] buffer = new byte[1024]; + int lengthRead; + while ((lengthRead = in.read(buffer)) > 0) { + out.write(buffer, 0, lengthRead); + out.flush(); + } + } + assertThat(copied).exists(); + assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); + } + + @Test + public void givenCommonsIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { + File copied = new File("src/test/resources/copiedWithApacheCommons.txt"); + FileUtils.copyFile(original, copied); + assertThat(copied).exists(); + assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); + } + + @Test + public void givenNIO2_whenCopied_thenCopyExistsWithSameContents() throws IOException { + Path copied = Paths.get("src/test/resources/copiedWithNio.txt"); + Path originalPath = original.toPath(); + Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING); + assertThat(copied).exists(); + assertThat(Files.readAllLines(originalPath).equals(Files.readAllLines(copied))); + } + + @Test + public void givenGuava_whenCopied_thenCopyExistsWithSameContents() throws IOException { + File copied = new File("src/test/resources/copiedWithApacheCommons.txt"); + com.google.common.io.Files.copy(original, copied); + assertThat(copied).exists(); + assertThat(Files.readAllLines(original.toPath()).equals(Files.readAllLines(copied.toPath()))); + } +} diff --git a/core-java-io/src/test/java/com/baeldung/csv/ReadCSVInArrayUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/csv/ReadCSVInArrayUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/csv/ReadCSVInArrayUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/csv/ReadCSVInArrayUnitTest.java diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java new file mode 100644 index 0000000000..5f4827bc21 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java @@ -0,0 +1,85 @@ +package com.baeldung.csv; + +import static org.junit.Assert.assertEquals; +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; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WriteCsvFileExampleUnitTest { + private static final Logger LOG = LoggerFactory.getLogger(WriteCsvFileExampleUnitTest.class); + + private WriteCsvFileExample csvExample; + + @Before + public void setupClass() { + csvExample = new WriteCsvFileExample(); + } + + @Test + public void givenCommaContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() { + String data = "three,two,one"; + String escapedData = csvExample.escapeSpecialCharacters(data); + + String expectedData = "\"three,two,one\""; + assertEquals(expectedData, escapedData); + } + + @Test + public void givenQuoteContainingData_whenEscapeSpecialCharacters_stringReturnedFormatted() { + String data = "She said \"Hello\""; + String escapedData = csvExample.escapeSpecialCharacters(data); + + String expectedData = "\"She said \"\"Hello\"\"\""; + assertEquals(expectedData, escapedData); + } + + @Test + public void givenNewlineContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() { + String dataNewline = "This contains\na newline"; + String dataCarriageReturn = "This contains\r\na newline and carriage return"; + String escapedDataNl = csvExample.escapeSpecialCharacters(dataNewline); + String escapedDataCr = csvExample.escapeSpecialCharacters(dataCarriageReturn); + + String expectedData = "This contains a newline"; + assertEquals(expectedData, escapedDataNl); + String expectedDataCr = "This contains a newline and carriage return"; + assertEquals(expectedDataCr, escapedDataCr); + } + + @Test + public void givenNonSpecialData_whenEscapeSpecialCharacters_stringReturnedUnchanged() { + String data = "This is nothing special"; + String returnedData = csvExample.escapeSpecialCharacters(data); + + assertEquals(data, returnedData); + } + + @Test + 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 = File.createTempFile("exampleOutput", ".csv"); + try (PrintWriter pw = new PrintWriter(csvOutputFile)) { + dataLines.stream() + .map(csvExample::convertToCSV) + .forEach(pw::println); + } catch (FileNotFoundException e) { + LOG.error("IOException " + e.getMessage()); + } + + assertTrue(csvOutputFile.exists()); + csvOutputFile.deleteOnExit(); + } +} diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java new file mode 100644 index 0000000000..d645782955 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java @@ -0,0 +1,100 @@ +package com.baeldung.directories; + +import org.junit.Before; +import org.junit.Test; + +import java.io.File; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NewDirectoryUnitTest { + + private static final File TEMP_DIRECTORY = new File(System.getProperty("java.io.tmpdir")); + + @Before + public void beforeEach() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File nestedInNewDirectory = new File(newDirectory, "nested_directory"); + File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory"); + File nestedInExistingDirectory = new File(existingDirectory, "nested_directory"); + + nestedInNewDirectory.delete(); + newDirectory.delete(); + nestedInExistingDirectory.delete(); + existingDirectory.mkdir(); + existingNestedDirectory.mkdir(); + } + + @Test + public void givenUnexistingDirectory_whenMkdir_thenTrue() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + assertFalse(newDirectory.exists()); + + boolean directoryCreated = newDirectory.mkdir(); + + assertTrue(directoryCreated); + } + + @Test + public void givenExistingDirectory_whenMkdir_thenFalse() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + newDirectory.mkdir(); + assertTrue(newDirectory.exists()); + + boolean directoryCreated = newDirectory.mkdir(); + + assertFalse(directoryCreated); + } + + @Test + public void givenUnexistingNestedDirectories_whenMkdir_thenFalse() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertFalse(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdir(); + + assertFalse(directoriesCreated); + } + + @Test + public void givenUnexistingNestedDirectories_whenMkdirs_thenTrue() { + File newDirectory = new File(System.getProperty("java.io.tmpdir") + File.separator + "new_directory"); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertFalse(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdirs(); + + assertTrue(directoriesCreated); + } + + @Test + public void givenExistingParentDirectories_whenMkdirs_thenTrue() { + File newDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + newDirectory.mkdir(); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertTrue(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdirs(); + + assertTrue(directoriesCreated); + } + + @Test + public void givenExistingNestedDirectories_whenMkdirs_thenFalse() { + File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory"); + assertTrue(existingDirectory.exists()); + assertTrue(existingNestedDirectory.exists()); + + boolean directoriesCreated = existingNestedDirectory.mkdirs(); + + assertFalse(directoriesCreated); + } + +} diff --git a/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/download/FileDownloadIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/extension/ExtensionUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/extension/ExtensionUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/extension/ExtensionUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/extension/ExtensionUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/file/FileOperationsManualTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FileOperationsManualTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/file/FileOperationsManualTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/file/FileOperationsManualTest.java diff --git a/core-java-io/src/test/java/com/baeldung/file/FilenameFilterManualTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilenameFilterManualTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/file/FilenameFilterManualTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilenameFilterManualTest.java diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java new file mode 100644 index 0000000000..8302124f32 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java @@ -0,0 +1,96 @@ +package com.baeldung.file; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.util.StreamUtils; + +public class FilesClearDataUnitTest { + + public static final String FILE_PATH = "src/test/resources/fileexample.txt"; + + @Before + @After + public void setup() throws IOException { + PrintWriter writer = new PrintWriter(FILE_PATH); + writer.print("This example shows how we can delete the file contents without deleting the file"); + writer.close(); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingPrintWritter_thenEmptyFile() throws IOException { + PrintWriter writer = new PrintWriter(FILE_PATH); + writer.print(""); + writer.close(); + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingPrintWritterWithougObject_thenEmptyFile() throws IOException { + new PrintWriter(FILE_PATH).close(); + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingFileWriter_thenEmptyFile() throws IOException { + new FileWriter(FILE_PATH, false).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingFileOutputStream_thenEmptyFile() throws IOException { + new FileOutputStream(FILE_PATH).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingFileUtils_thenEmptyFile() throws IOException { + FileUtils.write(new File(FILE_PATH), "", Charset.defaultCharset()); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingNIOFiles_thenEmptyFile() throws IOException { + BufferedWriter writer = Files.newBufferedWriter(Paths.get(FILE_PATH)); + writer.write(""); + writer.flush(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingNIOFileChannel_thenEmptyFile() throws IOException { + FileChannel.open(Paths.get(FILE_PATH), StandardOpenOption.WRITE).truncate(0).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingGuava_thenEmptyFile() throws IOException { + File file = new File(FILE_PATH); + byte[] empty = new byte[0]; + com.google.common.io.Files.write(empty, file); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } +} diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesManualTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilesManualTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/file/FilesManualTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/file/FilesManualTest.java diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java new file mode 100644 index 0000000000..65710121cc --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.file; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; + +import com.baeldung.files.ListFiles; + +public class ListFilesUnitTest { + + private ListFiles listFiles = new ListFiles(); + private String DIRECTORY = "src/test/resources/listFilesUnitTestFolder"; + private static final int DEPTH = 1; + private Set EXPECTED_FILE_LIST = new HashSet() { + { + add("test.xml"); + add("employee.json"); + add("students.json"); + add("country.txt"); + } + }; + + @Test + public void givenDir_whenUsingJAVAIO_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingJavaIO(DIRECTORY)); + } + + @Test + public void givenDir_whenWalkingTree_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalk(DIRECTORY,DEPTH)); + } + + @Test + public void givenDir_whenWalkingTreeWithVisitor_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalkAndVisitor(DIRECTORY)); + } + + @Test + public void givenDir_whenUsingDirectoryStream_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingDirectoryStream(DIRECTORY)); + } +} diff --git a/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java new file mode 100644 index 0000000000..6964ba80e3 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java @@ -0,0 +1,165 @@ +package com.baeldung.filechannel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +public class FileChannelUnitTest { + + @Test + public void givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel(); + ByteArrayOutputStream out = new ByteArrayOutputStream();) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + + assertEquals("Hello world", fileContent); + } + } + + @Test + public void givenFile_whenReadWithFileChannelUsingFileInputStream_thenCorrect() throws IOException { + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); + FileInputStream fin = new FileInputStream("src/test/resources/test_read.in"); + FileChannel channel = fin.getChannel();) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + + assertEquals("Hello world", fileContent); + } + } + + @Test + public void givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel(); + ByteArrayOutputStream out = new ByteArrayOutputStream();) { + + MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 6, 5); + + if (buff.hasRemaining()) { + byte[] data = new byte[buff.remaining()]; + buff.get(data); + assertEquals("world", new String(data, StandardCharsets.UTF_8)); + } + } + } + + @Test + public void whenWriteWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException { + String file = "src/test/resources/test_write_using_filechannel.txt"; + try (RandomAccessFile writer = new RandomAccessFile(file, "rw"); + FileChannel channel = writer.getChannel();) { + ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8)); + + channel.write(buff); + + // now we verify whether the file was written correctly + RandomAccessFile reader = new RandomAccessFile(file, "r"); + assertEquals("Hello world", reader.readLine()); + reader.close(); + } + } + + @Test + public void givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect() throws IOException { + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "rw"); + FileChannel channel = reader.getChannel(); + FileLock fileLock = channel.tryLock(6, 5, Boolean.FALSE);) { + + assertNotNull(fileLock); + } + } + + @Test + public void givenFile_whenReadWithFileChannelGetPosition_thenCorrect() throws IOException { + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); + RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel();) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + + // the original file is 11 bytes long, so that's where the position pointer should be + assertEquals(11, channel.position()); + + channel.position(4); + assertEquals(4, channel.position()); + } + } + + @Test + public void whenGetFileSize_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel();) { + + // the original file is 11 bytes long, so that's where the position pointer should be + assertEquals(11, channel.size()); + } + } + + @Test + public void whenTruncateFile_thenCorrect() throws IOException { + String input = "this is a test input"; + + FileOutputStream fout = new FileOutputStream("src/test/resources/test_truncate.txt"); + FileChannel channel = fout.getChannel(); + + ByteBuffer buff = ByteBuffer.wrap(input.getBytes()); + channel.write(buff); + buff.flip(); + + channel = channel.truncate(5); + assertEquals(5, channel.size()); + + fout.close(); + channel.close(); + } +} diff --git a/core-java-io/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/filesystem/jndi/test/LookupFSJNDIIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/filesystem/jndi/test/LookupFSJNDIIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/filesystem/jndi/test/LookupFSJNDIIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/filesystem/jndi/test/LookupFSJNDIIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio/selector/NioEchoLiveTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/FileIntegrationTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/PathManualTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/README.md b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/README.md similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/README.md rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/README.md diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoClient.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoIntegrationTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncEchoServer2.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/async/AsyncFileIntegrationTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java/nio2/attributes/BasicAttribsIntegrationTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java8/JavaFileSizeUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java8/JavaFileSizeUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java8/JavaFileSizeUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java8/JavaFileSizeUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/java8/JavaFolderSizeUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/java8/JavaFolderSizeUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/java8/JavaFolderSizeUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/java8/JavaFolderSizeUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/mappedbytebuffer/MappedByteBufferUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/stream/FileCopyUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/stream/FileCopyUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/stream/FileCopyUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/stream/FileCopyUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java b/core-java-modules/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java similarity index 100% rename from core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java rename to core-java-modules/core-java-io/src/test/java/com/baeldung/symlink/SymLinkExampleManualTest.java diff --git a/core-java-io/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionUnitTest.java diff --git a/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java new file mode 100644 index 0000000000..37f52fefea --- /dev/null +++ b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java @@ -0,0 +1,56 @@ +package org.baeldung.java.io; + +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +import static java.nio.channels.Channels.newChannel; +import static org.junit.Assert.assertEquals; + +public class InputStreamToByteBufferUnitTest { + + @Test + public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + while (initialStream.available() > 0) { + byteBuffer.put((byte) initialStream.read()); + } + + assertEquals(byteBuffer.position(), input.length); + } + + @Test + public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + InputStream initialStream = ByteSource + .wrap(new byte[] { 0, 1, 2 }) + .openStream(); + byte[] targetArray = ByteStreams.toByteArray(initialStream); + ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); + while (bufferByte.hasRemaining()) { + bufferByte.get(); + } + + assertEquals(bufferByte.position(), targetArray.length); + } + + @Test + public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + ReadableByteChannel channel = newChannel(initialStream); + IOUtils.readFully(channel, byteBuffer); + + assertEquals(byteBuffer.position(), input.length); + } + +} diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaFilePathUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaFilePathUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaFilePathUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaFilePathUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaFileUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaFileUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaFileUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaFileUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaReadFromFileUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaReadFromFileUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaReadFromFileUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaReadFromFileUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaScannerUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaScannerUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaScannerUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaScannerUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaWriteToFileUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaWriteToFileUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaWriteToFileUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaWriteToFileUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaXToByteArrayUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToByteArrayUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaXToByteArrayUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToByteArrayUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaXToInputStreamUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToInputStreamUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaXToInputStreamUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToInputStreamUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaXToReaderUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToReaderUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaXToReaderUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToReaderUnitTest.java diff --git a/core-java-io/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java b/core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java similarity index 100% rename from core-java-io/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java rename to core-java-modules/core-java-io/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java diff --git a/core-java-networking/src/test/resources/.gitignore b/core-java-modules/core-java-io/src/test/resources/.gitignore similarity index 100% rename from core-java-networking/src/test/resources/.gitignore rename to core-java-modules/core-java-io/src/test/resources/.gitignore diff --git a/core-java/src/test/resources/META-INF/mime.types b/core-java-modules/core-java-io/src/test/resources/META-INF/mime.types similarity index 100% rename from core-java/src/test/resources/META-INF/mime.types rename to core-java-modules/core-java-io/src/test/resources/META-INF/mime.types diff --git a/core-java-io/src/test/resources/anothersample.txt b/core-java-modules/core-java-io/src/test/resources/anothersample.txt similarity index 100% rename from core-java-io/src/test/resources/anothersample.txt rename to core-java-modules/core-java-io/src/test/resources/anothersample.txt diff --git a/core-java-io/src/test/resources/book.csv b/core-java-modules/core-java-io/src/test/resources/book.csv similarity index 100% rename from core-java-io/src/test/resources/book.csv rename to core-java-modules/core-java-io/src/test/resources/book.csv diff --git a/core-java-io/src/test/resources/configuration.properties b/core-java-modules/core-java-io/src/test/resources/configuration.properties similarity index 100% rename from core-java-io/src/test/resources/configuration.properties rename to core-java-modules/core-java-io/src/test/resources/configuration.properties diff --git a/core-java-io/src/test/resources/copiedWithApacheCommons.txt b/core-java-modules/core-java-io/src/test/resources/copiedWithApacheCommons.txt similarity index 100% rename from core-java-io/src/test/resources/copiedWithApacheCommons.txt rename to core-java-modules/core-java-io/src/test/resources/copiedWithApacheCommons.txt diff --git a/core-java-io/src/test/resources/copiedWithIo.txt b/core-java-modules/core-java-io/src/test/resources/copiedWithIo.txt similarity index 100% rename from core-java-io/src/test/resources/copiedWithIo.txt rename to core-java-modules/core-java-io/src/test/resources/copiedWithIo.txt diff --git a/core-java-io/src/test/resources/copiedWithNio.txt b/core-java-modules/core-java-io/src/test/resources/copiedWithNio.txt similarity index 100% rename from core-java-io/src/test/resources/copiedWithNio.txt rename to core-java-modules/core-java-io/src/test/resources/copiedWithNio.txt diff --git a/core-java-io/src/test/resources/copyTest/dest/readme.txt b/core-java-modules/core-java-io/src/test/resources/copyTest/dest/readme.txt similarity index 100% rename from core-java-io/src/test/resources/copyTest/dest/readme.txt rename to core-java-modules/core-java-io/src/test/resources/copyTest/dest/readme.txt diff --git a/core-java-io/src/test/resources/copyTest/src/test_apache.txt b/core-java-modules/core-java-io/src/test/resources/copyTest/src/test_apache.txt similarity index 100% rename from core-java-io/src/test/resources/copyTest/src/test_apache.txt rename to core-java-modules/core-java-io/src/test/resources/copyTest/src/test_apache.txt diff --git a/core-java-io/src/test/resources/copyTest/src/test_channel.txt b/core-java-modules/core-java-io/src/test/resources/copyTest/src/test_channel.txt similarity index 100% rename from core-java-io/src/test/resources/copyTest/src/test_channel.txt rename to core-java-modules/core-java-io/src/test/resources/copyTest/src/test_channel.txt diff --git a/core-java-io/src/test/resources/copyTest/src/test_files.txt b/core-java-modules/core-java-io/src/test/resources/copyTest/src/test_files.txt similarity index 100% rename from core-java-io/src/test/resources/copyTest/src/test_files.txt rename to core-java-modules/core-java-io/src/test/resources/copyTest/src/test_files.txt diff --git a/core-java-io/src/test/resources/copyTest/src/test_stream.txt b/core-java-modules/core-java-io/src/test/resources/copyTest/src/test_stream.txt similarity index 100% rename from core-java-io/src/test/resources/copyTest/src/test_stream.txt rename to core-java-modules/core-java-io/src/test/resources/copyTest/src/test_stream.txt diff --git a/core-java-io/src/test/resources/dictionary.in b/core-java-modules/core-java-io/src/test/resources/dictionary.in similarity index 100% rename from core-java-io/src/test/resources/dictionary.in rename to core-java-modules/core-java-io/src/test/resources/dictionary.in diff --git a/core-java-io/src/test/resources/file.txt b/core-java-modules/core-java-io/src/test/resources/file.txt similarity index 100% rename from core-java-io/src/test/resources/file.txt rename to core-java-modules/core-java-io/src/test/resources/file.txt diff --git a/core-java-io/src/test/resources/fileNameFilterManualTestFolder/people.json b/core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/people.json similarity index 100% rename from core-java-io/src/test/resources/fileNameFilterManualTestFolder/people.json rename to core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/people.json diff --git a/core-java-io/src/test/resources/fileNameFilterManualTestFolder/students.json b/core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/students.json similarity index 100% rename from core-java-io/src/test/resources/fileNameFilterManualTestFolder/students.json rename to core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/students.json diff --git a/core-java-io/src/test/resources/fileNameFilterManualTestFolder/teachers.xml b/core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/teachers.xml similarity index 100% rename from core-java-io/src/test/resources/fileNameFilterManualTestFolder/teachers.xml rename to core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/teachers.xml diff --git a/core-java-io/src/test/resources/fileNameFilterManualTestFolder/workers.xml b/core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/workers.xml similarity index 100% rename from core-java-io/src/test/resources/fileNameFilterManualTestFolder/workers.xml rename to core-java-modules/core-java-io/src/test/resources/fileNameFilterManualTestFolder/workers.xml diff --git a/core-java-io/src/test/resources/fileTest.txt b/core-java-modules/core-java-io/src/test/resources/fileTest.txt similarity index 100% rename from core-java-io/src/test/resources/fileTest.txt rename to core-java-modules/core-java-io/src/test/resources/fileTest.txt diff --git a/core-java-io/src/test/resources/fileToRead.txt b/core-java-modules/core-java-io/src/test/resources/fileToRead.txt similarity index 100% rename from core-java-io/src/test/resources/fileToRead.txt rename to core-java-modules/core-java-io/src/test/resources/fileToRead.txt diff --git a/core-java-io/src/test/resources/fileToWriteTo.txt b/core-java-modules/core-java-io/src/test/resources/fileToWriteTo.txt similarity index 100% rename from core-java-io/src/test/resources/fileToWriteTo.txt rename to core-java-modules/core-java-io/src/test/resources/fileToWriteTo.txt diff --git a/core-java-modules/core-java-io/src/test/resources/fileexample.txt b/core-java-modules/core-java-io/src/test/resources/fileexample.txt new file mode 100644 index 0000000000..ee48fdfb84 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/fileexample.txt @@ -0,0 +1 @@ +This example shows how we can delete the file contents without deleting the file \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg b/core-java-modules/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg new file mode 100644 index 0000000000..77c459b0e3 Binary files /dev/null and b/core-java-modules/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg differ diff --git a/core-java-io/src/test/resources/initialFile.txt b/core-java-modules/core-java-io/src/test/resources/initialFile.txt similarity index 100% rename from core-java-io/src/test/resources/initialFile.txt rename to core-java-modules/core-java-io/src/test/resources/initialFile.txt diff --git a/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt new file mode 100644 index 0000000000..45bfe896dc --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt @@ -0,0 +1 @@ +This is a sample txt file for unit test ListFilesUnitTest \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml new file mode 100644 index 0000000000..19b16cc72c --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/core-java-io/src/test/resources/original.txt b/core-java-modules/core-java-io/src/test/resources/original.txt similarity index 100% rename from core-java-io/src/test/resources/original.txt rename to core-java-modules/core-java-io/src/test/resources/original.txt diff --git a/core-java/src/main/resources/product.png b/core-java-modules/core-java-io/src/test/resources/product.png similarity index 100% rename from core-java/src/main/resources/product.png rename to core-java-modules/core-java-io/src/test/resources/product.png diff --git a/core-java-io/src/test/resources/sample.txt b/core-java-modules/core-java-io/src/test/resources/sample.txt similarity index 100% rename from core-java-io/src/test/resources/sample.txt rename to core-java-modules/core-java-io/src/test/resources/sample.txt diff --git a/core-java-io/src/test/resources/sampleNumberFile.txt b/core-java-modules/core-java-io/src/test/resources/sampleNumberFile.txt similarity index 100% rename from core-java-io/src/test/resources/sampleNumberFile.txt rename to core-java-modules/core-java-io/src/test/resources/sampleNumberFile.txt diff --git a/core-java-io/src/test/resources/sampleTextFile.txt b/core-java-modules/core-java-io/src/test/resources/sampleTextFile.txt similarity index 100% rename from core-java-io/src/test/resources/sampleTextFile.txt rename to core-java-modules/core-java-io/src/test/resources/sampleTextFile.txt diff --git a/core-java-io/src/test/resources/targetFile.tmp b/core-java-modules/core-java-io/src/test/resources/targetFile.tmp similarity index 100% rename from core-java-io/src/test/resources/targetFile.tmp rename to core-java-modules/core-java-io/src/test/resources/targetFile.tmp diff --git a/core-java-io/src/test/resources/targetFile.txt b/core-java-modules/core-java-io/src/test/resources/targetFile.txt similarity index 100% rename from core-java-io/src/test/resources/targetFile.txt rename to core-java-modules/core-java-io/src/test/resources/targetFile.txt diff --git a/core-java-io/src/test/resources/test.find b/core-java-modules/core-java-io/src/test/resources/test.find similarity index 100% rename from core-java-io/src/test/resources/test.find rename to core-java-modules/core-java-io/src/test/resources/test.find diff --git a/core-java-io/src/test/resources/testFolder/sample_file_1.in b/core-java-modules/core-java-io/src/test/resources/testFolder/sample_file_1.in similarity index 100% rename from core-java-io/src/test/resources/testFolder/sample_file_1.in rename to core-java-modules/core-java-io/src/test/resources/testFolder/sample_file_1.in diff --git a/core-java-io/src/test/resources/testFolder/sample_file_2.in b/core-java-modules/core-java-io/src/test/resources/testFolder/sample_file_2.in similarity index 100% rename from core-java-io/src/test/resources/testFolder/sample_file_2.in rename to core-java-modules/core-java-io/src/test/resources/testFolder/sample_file_2.in diff --git a/core-java-io/src/test/resources/test_read.in b/core-java-modules/core-java-io/src/test/resources/test_read.in similarity index 100% rename from core-java-io/src/test/resources/test_read.in rename to core-java-modules/core-java-io/src/test/resources/test_read.in diff --git a/core-java-io/src/test/resources/test_read1.in b/core-java-modules/core-java-io/src/test/resources/test_read1.in similarity index 100% rename from core-java-io/src/test/resources/test_read1.in rename to core-java-modules/core-java-io/src/test/resources/test_read1.in diff --git a/core-java-io/src/test/resources/test_read2.in b/core-java-modules/core-java-io/src/test/resources/test_read2.in similarity index 100% rename from core-java-io/src/test/resources/test_read2.in rename to core-java-modules/core-java-io/src/test/resources/test_read2.in diff --git a/core-java-io/src/test/resources/test_read3.in b/core-java-modules/core-java-io/src/test/resources/test_read3.in similarity index 100% rename from core-java-io/src/test/resources/test_read3.in rename to core-java-modules/core-java-io/src/test/resources/test_read3.in diff --git a/core-java-io/src/test/resources/test_read4.in b/core-java-modules/core-java-io/src/test/resources/test_read4.in similarity index 100% rename from core-java-io/src/test/resources/test_read4.in rename to core-java-modules/core-java-io/src/test/resources/test_read4.in diff --git a/core-java-io/src/test/resources/test_read7.in b/core-java-modules/core-java-io/src/test/resources/test_read7.in similarity index 100% rename from core-java-io/src/test/resources/test_read7.in rename to core-java-modules/core-java-io/src/test/resources/test_read7.in diff --git a/core-java-io/src/test/resources/test_read8.in b/core-java-modules/core-java-io/src/test/resources/test_read8.in similarity index 100% rename from core-java-io/src/test/resources/test_read8.in rename to core-java-modules/core-java-io/src/test/resources/test_read8.in diff --git a/core-java-io/src/test/resources/test_read_d.in b/core-java-modules/core-java-io/src/test/resources/test_read_d.in similarity index 100% rename from core-java-io/src/test/resources/test_read_d.in rename to core-java-modules/core-java-io/src/test/resources/test_read_d.in diff --git a/core-java-io/src/test/resources/test_read_multiple.in b/core-java-modules/core-java-io/src/test/resources/test_read_multiple.in similarity index 100% rename from core-java-io/src/test/resources/test_read_multiple.in rename to core-java-modules/core-java-io/src/test/resources/test_read_multiple.in diff --git a/core-java-modules/core-java-io/src/test/resources/test_truncate.txt b/core-java-modules/core-java-io/src/test/resources/test_truncate.txt new file mode 100644 index 0000000000..26d3b38cdd --- /dev/null +++ b/core-java-modules/core-java-io/src/test/resources/test_truncate.txt @@ -0,0 +1 @@ +this \ No newline at end of file diff --git a/core-java-io/src/test/resources/test_write.txt b/core-java-modules/core-java-io/src/test/resources/test_write.txt similarity index 100% rename from core-java-io/src/test/resources/test_write.txt rename to core-java-modules/core-java-io/src/test/resources/test_write.txt diff --git a/core-java-io/src/test/resources/test_write_1.txt b/core-java-modules/core-java-io/src/test/resources/test_write_1.txt similarity index 100% rename from core-java-io/src/test/resources/test_write_1.txt rename to core-java-modules/core-java-io/src/test/resources/test_write_1.txt diff --git a/core-java-io/src/test/resources/test_write_2.txt b/core-java-modules/core-java-io/src/test/resources/test_write_2.txt similarity index 100% rename from core-java-io/src/test/resources/test_write_2.txt rename to core-java-modules/core-java-io/src/test/resources/test_write_2.txt diff --git a/core-java-io/src/test/resources/test_write_3.txt b/core-java-modules/core-java-io/src/test/resources/test_write_3.txt similarity index 100% rename from core-java-io/src/test/resources/test_write_3.txt rename to core-java-modules/core-java-io/src/test/resources/test_write_3.txt diff --git a/core-java-io/src/test/resources/test_write_4.txt b/core-java-modules/core-java-io/src/test/resources/test_write_4.txt similarity index 100% rename from core-java-io/src/test/resources/test_write_4.txt rename to core-java-modules/core-java-io/src/test/resources/test_write_4.txt diff --git a/core-java-io/src/test/resources/test_write_5.txt b/core-java-modules/core-java-io/src/test/resources/test_write_5.txt similarity index 100% rename from core-java-io/src/test/resources/test_write_5.txt rename to core-java-modules/core-java-io/src/test/resources/test_write_5.txt diff --git a/core-java/src/test/resources/test_read.in b/core-java-modules/core-java-io/src/test/resources/test_write_using_filechannel.txt similarity index 100% rename from core-java/src/test/resources/test_read.in rename to core-java-modules/core-java-io/src/test/resources/test_write_using_filechannel.txt diff --git a/core-java-modules/core-java-io/target_link.txt b/core-java-modules/core-java-io/target_link.txt new file mode 100644 index 0000000000..931a810b8d --- /dev/null +++ b/core-java-modules/core-java-io/target_link.txt @@ -0,0 +1,10000 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 +4669 +4670 +4671 +4672 +4673 +4674 +4675 +4676 +4677 +4678 +4679 +4680 +4681 +4682 +4683 +4684 +4685 +4686 +4687 +4688 +4689 +4690 +4691 +4692 +4693 +4694 +4695 +4696 +4697 +4698 +4699 +4700 +4701 +4702 +4703 +4704 +4705 +4706 +4707 +4708 +4709 +4710 +4711 +4712 +4713 +4714 +4715 +4716 +4717 +4718 +4719 +4720 +4721 +4722 +4723 +4724 +4725 +4726 +4727 +4728 +4729 +4730 +4731 +4732 +4733 +4734 +4735 +4736 +4737 +4738 +4739 +4740 +4741 +4742 +4743 +4744 +4745 +4746 +4747 +4748 +4749 +4750 +4751 +4752 +4753 +4754 +4755 +4756 +4757 +4758 +4759 +4760 +4761 +4762 +4763 +4764 +4765 +4766 +4767 +4768 +4769 +4770 +4771 +4772 +4773 +4774 +4775 +4776 +4777 +4778 +4779 +4780 +4781 +4782 +4783 +4784 +4785 +4786 +4787 +4788 +4789 +4790 +4791 +4792 +4793 +4794 +4795 +4796 +4797 +4798 +4799 +4800 +4801 +4802 +4803 +4804 +4805 +4806 +4807 +4808 +4809 +4810 +4811 +4812 +4813 +4814 +4815 +4816 +4817 +4818 +4819 +4820 +4821 +4822 +4823 +4824 +4825 +4826 +4827 +4828 +4829 +4830 +4831 +4832 +4833 +4834 +4835 +4836 +4837 +4838 +4839 +4840 +4841 +4842 +4843 +4844 +4845 +4846 +4847 +4848 +4849 +4850 +4851 +4852 +4853 +4854 +4855 +4856 +4857 +4858 +4859 +4860 +4861 +4862 +4863 +4864 +4865 +4866 +4867 +4868 +4869 +4870 +4871 +4872 +4873 +4874 +4875 +4876 +4877 +4878 +4879 +4880 +4881 +4882 +4883 +4884 +4885 +4886 +4887 +4888 +4889 +4890 +4891 +4892 +4893 +4894 +4895 +4896 +4897 +4898 +4899 +4900 +4901 +4902 +4903 +4904 +4905 +4906 +4907 +4908 +4909 +4910 +4911 +4912 +4913 +4914 +4915 +4916 +4917 +4918 +4919 +4920 +4921 +4922 +4923 +4924 +4925 +4926 +4927 +4928 +4929 +4930 +4931 +4932 +4933 +4934 +4935 +4936 +4937 +4938 +4939 +4940 +4941 +4942 +4943 +4944 +4945 +4946 +4947 +4948 +4949 +4950 +4951 +4952 +4953 +4954 +4955 +4956 +4957 +4958 +4959 +4960 +4961 +4962 +4963 +4964 +4965 +4966 +4967 +4968 +4969 +4970 +4971 +4972 +4973 +4974 +4975 +4976 +4977 +4978 +4979 +4980 +4981 +4982 +4983 +4984 +4985 +4986 +4987 +4988 +4989 +4990 +4991 +4992 +4993 +4994 +4995 +4996 +4997 +4998 +4999 +5000 +5001 +5002 +5003 +5004 +5005 +5006 +5007 +5008 +5009 +5010 +5011 +5012 +5013 +5014 +5015 +5016 +5017 +5018 +5019 +5020 +5021 +5022 +5023 +5024 +5025 +5026 +5027 +5028 +5029 +5030 +5031 +5032 +5033 +5034 +5035 +5036 +5037 +5038 +5039 +5040 +5041 +5042 +5043 +5044 +5045 +5046 +5047 +5048 +5049 +5050 +5051 +5052 +5053 +5054 +5055 +5056 +5057 +5058 +5059 +5060 +5061 +5062 +5063 +5064 +5065 +5066 +5067 +5068 +5069 +5070 +5071 +5072 +5073 +5074 +5075 +5076 +5077 +5078 +5079 +5080 +5081 +5082 +5083 +5084 +5085 +5086 +5087 +5088 +5089 +5090 +5091 +5092 +5093 +5094 +5095 +5096 +5097 +5098 +5099 +5100 +5101 +5102 +5103 +5104 +5105 +5106 +5107 +5108 +5109 +5110 +5111 +5112 +5113 +5114 +5115 +5116 +5117 +5118 +5119 +5120 +5121 +5122 +5123 +5124 +5125 +5126 +5127 +5128 +5129 +5130 +5131 +5132 +5133 +5134 +5135 +5136 +5137 +5138 +5139 +5140 +5141 +5142 +5143 +5144 +5145 +5146 +5147 +5148 +5149 +5150 +5151 +5152 +5153 +5154 +5155 +5156 +5157 +5158 +5159 +5160 +5161 +5162 +5163 +5164 +5165 +5166 +5167 +5168 +5169 +5170 +5171 +5172 +5173 +5174 +5175 +5176 +5177 +5178 +5179 +5180 +5181 +5182 +5183 +5184 +5185 +5186 +5187 +5188 +5189 +5190 +5191 +5192 +5193 +5194 +5195 +5196 +5197 +5198 +5199 +5200 +5201 +5202 +5203 +5204 +5205 +5206 +5207 +5208 +5209 +5210 +5211 +5212 +5213 +5214 +5215 +5216 +5217 +5218 +5219 +5220 +5221 +5222 +5223 +5224 +5225 +5226 +5227 +5228 +5229 +5230 +5231 +5232 +5233 +5234 +5235 +5236 +5237 +5238 +5239 +5240 +5241 +5242 +5243 +5244 +5245 +5246 +5247 +5248 +5249 +5250 +5251 +5252 +5253 +5254 +5255 +5256 +5257 +5258 +5259 +5260 +5261 +5262 +5263 +5264 +5265 +5266 +5267 +5268 +5269 +5270 +5271 +5272 +5273 +5274 +5275 +5276 +5277 +5278 +5279 +5280 +5281 +5282 +5283 +5284 +5285 +5286 +5287 +5288 +5289 +5290 +5291 +5292 +5293 +5294 +5295 +5296 +5297 +5298 +5299 +5300 +5301 +5302 +5303 +5304 +5305 +5306 +5307 +5308 +5309 +5310 +5311 +5312 +5313 +5314 +5315 +5316 +5317 +5318 +5319 +5320 +5321 +5322 +5323 +5324 +5325 +5326 +5327 +5328 +5329 +5330 +5331 +5332 +5333 +5334 +5335 +5336 +5337 +5338 +5339 +5340 +5341 +5342 +5343 +5344 +5345 +5346 +5347 +5348 +5349 +5350 +5351 +5352 +5353 +5354 +5355 +5356 +5357 +5358 +5359 +5360 +5361 +5362 +5363 +5364 +5365 +5366 +5367 +5368 +5369 +5370 +5371 +5372 +5373 +5374 +5375 +5376 +5377 +5378 +5379 +5380 +5381 +5382 +5383 +5384 +5385 +5386 +5387 +5388 +5389 +5390 +5391 +5392 +5393 +5394 +5395 +5396 +5397 +5398 +5399 +5400 +5401 +5402 +5403 +5404 +5405 +5406 +5407 +5408 +5409 +5410 +5411 +5412 +5413 +5414 +5415 +5416 +5417 +5418 +5419 +5420 +5421 +5422 +5423 +5424 +5425 +5426 +5427 +5428 +5429 +5430 +5431 +5432 +5433 +5434 +5435 +5436 +5437 +5438 +5439 +5440 +5441 +5442 +5443 +5444 +5445 +5446 +5447 +5448 +5449 +5450 +5451 +5452 +5453 +5454 +5455 +5456 +5457 +5458 +5459 +5460 +5461 +5462 +5463 +5464 +5465 +5466 +5467 +5468 +5469 +5470 +5471 +5472 +5473 +5474 +5475 +5476 +5477 +5478 +5479 +5480 +5481 +5482 +5483 +5484 +5485 +5486 +5487 +5488 +5489 +5490 +5491 +5492 +5493 +5494 +5495 +5496 +5497 +5498 +5499 +5500 +5501 +5502 +5503 +5504 +5505 +5506 +5507 +5508 +5509 +5510 +5511 +5512 +5513 +5514 +5515 +5516 +5517 +5518 +5519 +5520 +5521 +5522 +5523 +5524 +5525 +5526 +5527 +5528 +5529 +5530 +5531 +5532 +5533 +5534 +5535 +5536 +5537 +5538 +5539 +5540 +5541 +5542 +5543 +5544 +5545 +5546 +5547 +5548 +5549 +5550 +5551 +5552 +5553 +5554 +5555 +5556 +5557 +5558 +5559 +5560 +5561 +5562 +5563 +5564 +5565 +5566 +5567 +5568 +5569 +5570 +5571 +5572 +5573 +5574 +5575 +5576 +5577 +5578 +5579 +5580 +5581 +5582 +5583 +5584 +5585 +5586 +5587 +5588 +5589 +5590 +5591 +5592 +5593 +5594 +5595 +5596 +5597 +5598 +5599 +5600 +5601 +5602 +5603 +5604 +5605 +5606 +5607 +5608 +5609 +5610 +5611 +5612 +5613 +5614 +5615 +5616 +5617 +5618 +5619 +5620 +5621 +5622 +5623 +5624 +5625 +5626 +5627 +5628 +5629 +5630 +5631 +5632 +5633 +5634 +5635 +5636 +5637 +5638 +5639 +5640 +5641 +5642 +5643 +5644 +5645 +5646 +5647 +5648 +5649 +5650 +5651 +5652 +5653 +5654 +5655 +5656 +5657 +5658 +5659 +5660 +5661 +5662 +5663 +5664 +5665 +5666 +5667 +5668 +5669 +5670 +5671 +5672 +5673 +5674 +5675 +5676 +5677 +5678 +5679 +5680 +5681 +5682 +5683 +5684 +5685 +5686 +5687 +5688 +5689 +5690 +5691 +5692 +5693 +5694 +5695 +5696 +5697 +5698 +5699 +5700 +5701 +5702 +5703 +5704 +5705 +5706 +5707 +5708 +5709 +5710 +5711 +5712 +5713 +5714 +5715 +5716 +5717 +5718 +5719 +5720 +5721 +5722 +5723 +5724 +5725 +5726 +5727 +5728 +5729 +5730 +5731 +5732 +5733 +5734 +5735 +5736 +5737 +5738 +5739 +5740 +5741 +5742 +5743 +5744 +5745 +5746 +5747 +5748 +5749 +5750 +5751 +5752 +5753 +5754 +5755 +5756 +5757 +5758 +5759 +5760 +5761 +5762 +5763 +5764 +5765 +5766 +5767 +5768 +5769 +5770 +5771 +5772 +5773 +5774 +5775 +5776 +5777 +5778 +5779 +5780 +5781 +5782 +5783 +5784 +5785 +5786 +5787 +5788 +5789 +5790 +5791 +5792 +5793 +5794 +5795 +5796 +5797 +5798 +5799 +5800 +5801 +5802 +5803 +5804 +5805 +5806 +5807 +5808 +5809 +5810 +5811 +5812 +5813 +5814 +5815 +5816 +5817 +5818 +5819 +5820 +5821 +5822 +5823 +5824 +5825 +5826 +5827 +5828 +5829 +5830 +5831 +5832 +5833 +5834 +5835 +5836 +5837 +5838 +5839 +5840 +5841 +5842 +5843 +5844 +5845 +5846 +5847 +5848 +5849 +5850 +5851 +5852 +5853 +5854 +5855 +5856 +5857 +5858 +5859 +5860 +5861 +5862 +5863 +5864 +5865 +5866 +5867 +5868 +5869 +5870 +5871 +5872 +5873 +5874 +5875 +5876 +5877 +5878 +5879 +5880 +5881 +5882 +5883 +5884 +5885 +5886 +5887 +5888 +5889 +5890 +5891 +5892 +5893 +5894 +5895 +5896 +5897 +5898 +5899 +5900 +5901 +5902 +5903 +5904 +5905 +5906 +5907 +5908 +5909 +5910 +5911 +5912 +5913 +5914 +5915 +5916 +5917 +5918 +5919 +5920 +5921 +5922 +5923 +5924 +5925 +5926 +5927 +5928 +5929 +5930 +5931 +5932 +5933 +5934 +5935 +5936 +5937 +5938 +5939 +5940 +5941 +5942 +5943 +5944 +5945 +5946 +5947 +5948 +5949 +5950 +5951 +5952 +5953 +5954 +5955 +5956 +5957 +5958 +5959 +5960 +5961 +5962 +5963 +5964 +5965 +5966 +5967 +5968 +5969 +5970 +5971 +5972 +5973 +5974 +5975 +5976 +5977 +5978 +5979 +5980 +5981 +5982 +5983 +5984 +5985 +5986 +5987 +5988 +5989 +5990 +5991 +5992 +5993 +5994 +5995 +5996 +5997 +5998 +5999 +6000 +6001 +6002 +6003 +6004 +6005 +6006 +6007 +6008 +6009 +6010 +6011 +6012 +6013 +6014 +6015 +6016 +6017 +6018 +6019 +6020 +6021 +6022 +6023 +6024 +6025 +6026 +6027 +6028 +6029 +6030 +6031 +6032 +6033 +6034 +6035 +6036 +6037 +6038 +6039 +6040 +6041 +6042 +6043 +6044 +6045 +6046 +6047 +6048 +6049 +6050 +6051 +6052 +6053 +6054 +6055 +6056 +6057 +6058 +6059 +6060 +6061 +6062 +6063 +6064 +6065 +6066 +6067 +6068 +6069 +6070 +6071 +6072 +6073 +6074 +6075 +6076 +6077 +6078 +6079 +6080 +6081 +6082 +6083 +6084 +6085 +6086 +6087 +6088 +6089 +6090 +6091 +6092 +6093 +6094 +6095 +6096 +6097 +6098 +6099 +6100 +6101 +6102 +6103 +6104 +6105 +6106 +6107 +6108 +6109 +6110 +6111 +6112 +6113 +6114 +6115 +6116 +6117 +6118 +6119 +6120 +6121 +6122 +6123 +6124 +6125 +6126 +6127 +6128 +6129 +6130 +6131 +6132 +6133 +6134 +6135 +6136 +6137 +6138 +6139 +6140 +6141 +6142 +6143 +6144 +6145 +6146 +6147 +6148 +6149 +6150 +6151 +6152 +6153 +6154 +6155 +6156 +6157 +6158 +6159 +6160 +6161 +6162 +6163 +6164 +6165 +6166 +6167 +6168 +6169 +6170 +6171 +6172 +6173 +6174 +6175 +6176 +6177 +6178 +6179 +6180 +6181 +6182 +6183 +6184 +6185 +6186 +6187 +6188 +6189 +6190 +6191 +6192 +6193 +6194 +6195 +6196 +6197 +6198 +6199 +6200 +6201 +6202 +6203 +6204 +6205 +6206 +6207 +6208 +6209 +6210 +6211 +6212 +6213 +6214 +6215 +6216 +6217 +6218 +6219 +6220 +6221 +6222 +6223 +6224 +6225 +6226 +6227 +6228 +6229 +6230 +6231 +6232 +6233 +6234 +6235 +6236 +6237 +6238 +6239 +6240 +6241 +6242 +6243 +6244 +6245 +6246 +6247 +6248 +6249 +6250 +6251 +6252 +6253 +6254 +6255 +6256 +6257 +6258 +6259 +6260 +6261 +6262 +6263 +6264 +6265 +6266 +6267 +6268 +6269 +6270 +6271 +6272 +6273 +6274 +6275 +6276 +6277 +6278 +6279 +6280 +6281 +6282 +6283 +6284 +6285 +6286 +6287 +6288 +6289 +6290 +6291 +6292 +6293 +6294 +6295 +6296 +6297 +6298 +6299 +6300 +6301 +6302 +6303 +6304 +6305 +6306 +6307 +6308 +6309 +6310 +6311 +6312 +6313 +6314 +6315 +6316 +6317 +6318 +6319 +6320 +6321 +6322 +6323 +6324 +6325 +6326 +6327 +6328 +6329 +6330 +6331 +6332 +6333 +6334 +6335 +6336 +6337 +6338 +6339 +6340 +6341 +6342 +6343 +6344 +6345 +6346 +6347 +6348 +6349 +6350 +6351 +6352 +6353 +6354 +6355 +6356 +6357 +6358 +6359 +6360 +6361 +6362 +6363 +6364 +6365 +6366 +6367 +6368 +6369 +6370 +6371 +6372 +6373 +6374 +6375 +6376 +6377 +6378 +6379 +6380 +6381 +6382 +6383 +6384 +6385 +6386 +6387 +6388 +6389 +6390 +6391 +6392 +6393 +6394 +6395 +6396 +6397 +6398 +6399 +6400 +6401 +6402 +6403 +6404 +6405 +6406 +6407 +6408 +6409 +6410 +6411 +6412 +6413 +6414 +6415 +6416 +6417 +6418 +6419 +6420 +6421 +6422 +6423 +6424 +6425 +6426 +6427 +6428 +6429 +6430 +6431 +6432 +6433 +6434 +6435 +6436 +6437 +6438 +6439 +6440 +6441 +6442 +6443 +6444 +6445 +6446 +6447 +6448 +6449 +6450 +6451 +6452 +6453 +6454 +6455 +6456 +6457 +6458 +6459 +6460 +6461 +6462 +6463 +6464 +6465 +6466 +6467 +6468 +6469 +6470 +6471 +6472 +6473 +6474 +6475 +6476 +6477 +6478 +6479 +6480 +6481 +6482 +6483 +6484 +6485 +6486 +6487 +6488 +6489 +6490 +6491 +6492 +6493 +6494 +6495 +6496 +6497 +6498 +6499 +6500 +6501 +6502 +6503 +6504 +6505 +6506 +6507 +6508 +6509 +6510 +6511 +6512 +6513 +6514 +6515 +6516 +6517 +6518 +6519 +6520 +6521 +6522 +6523 +6524 +6525 +6526 +6527 +6528 +6529 +6530 +6531 +6532 +6533 +6534 +6535 +6536 +6537 +6538 +6539 +6540 +6541 +6542 +6543 +6544 +6545 +6546 +6547 +6548 +6549 +6550 +6551 +6552 +6553 +6554 +6555 +6556 +6557 +6558 +6559 +6560 +6561 +6562 +6563 +6564 +6565 +6566 +6567 +6568 +6569 +6570 +6571 +6572 +6573 +6574 +6575 +6576 +6577 +6578 +6579 +6580 +6581 +6582 +6583 +6584 +6585 +6586 +6587 +6588 +6589 +6590 +6591 +6592 +6593 +6594 +6595 +6596 +6597 +6598 +6599 +6600 +6601 +6602 +6603 +6604 +6605 +6606 +6607 +6608 +6609 +6610 +6611 +6612 +6613 +6614 +6615 +6616 +6617 +6618 +6619 +6620 +6621 +6622 +6623 +6624 +6625 +6626 +6627 +6628 +6629 +6630 +6631 +6632 +6633 +6634 +6635 +6636 +6637 +6638 +6639 +6640 +6641 +6642 +6643 +6644 +6645 +6646 +6647 +6648 +6649 +6650 +6651 +6652 +6653 +6654 +6655 +6656 +6657 +6658 +6659 +6660 +6661 +6662 +6663 +6664 +6665 +6666 +6667 +6668 +6669 +6670 +6671 +6672 +6673 +6674 +6675 +6676 +6677 +6678 +6679 +6680 +6681 +6682 +6683 +6684 +6685 +6686 +6687 +6688 +6689 +6690 +6691 +6692 +6693 +6694 +6695 +6696 +6697 +6698 +6699 +6700 +6701 +6702 +6703 +6704 +6705 +6706 +6707 +6708 +6709 +6710 +6711 +6712 +6713 +6714 +6715 +6716 +6717 +6718 +6719 +6720 +6721 +6722 +6723 +6724 +6725 +6726 +6727 +6728 +6729 +6730 +6731 +6732 +6733 +6734 +6735 +6736 +6737 +6738 +6739 +6740 +6741 +6742 +6743 +6744 +6745 +6746 +6747 +6748 +6749 +6750 +6751 +6752 +6753 +6754 +6755 +6756 +6757 +6758 +6759 +6760 +6761 +6762 +6763 +6764 +6765 +6766 +6767 +6768 +6769 +6770 +6771 +6772 +6773 +6774 +6775 +6776 +6777 +6778 +6779 +6780 +6781 +6782 +6783 +6784 +6785 +6786 +6787 +6788 +6789 +6790 +6791 +6792 +6793 +6794 +6795 +6796 +6797 +6798 +6799 +6800 +6801 +6802 +6803 +6804 +6805 +6806 +6807 +6808 +6809 +6810 +6811 +6812 +6813 +6814 +6815 +6816 +6817 +6818 +6819 +6820 +6821 +6822 +6823 +6824 +6825 +6826 +6827 +6828 +6829 +6830 +6831 +6832 +6833 +6834 +6835 +6836 +6837 +6838 +6839 +6840 +6841 +6842 +6843 +6844 +6845 +6846 +6847 +6848 +6849 +6850 +6851 +6852 +6853 +6854 +6855 +6856 +6857 +6858 +6859 +6860 +6861 +6862 +6863 +6864 +6865 +6866 +6867 +6868 +6869 +6870 +6871 +6872 +6873 +6874 +6875 +6876 +6877 +6878 +6879 +6880 +6881 +6882 +6883 +6884 +6885 +6886 +6887 +6888 +6889 +6890 +6891 +6892 +6893 +6894 +6895 +6896 +6897 +6898 +6899 +6900 +6901 +6902 +6903 +6904 +6905 +6906 +6907 +6908 +6909 +6910 +6911 +6912 +6913 +6914 +6915 +6916 +6917 +6918 +6919 +6920 +6921 +6922 +6923 +6924 +6925 +6926 +6927 +6928 +6929 +6930 +6931 +6932 +6933 +6934 +6935 +6936 +6937 +6938 +6939 +6940 +6941 +6942 +6943 +6944 +6945 +6946 +6947 +6948 +6949 +6950 +6951 +6952 +6953 +6954 +6955 +6956 +6957 +6958 +6959 +6960 +6961 +6962 +6963 +6964 +6965 +6966 +6967 +6968 +6969 +6970 +6971 +6972 +6973 +6974 +6975 +6976 +6977 +6978 +6979 +6980 +6981 +6982 +6983 +6984 +6985 +6986 +6987 +6988 +6989 +6990 +6991 +6992 +6993 +6994 +6995 +6996 +6997 +6998 +6999 +7000 +7001 +7002 +7003 +7004 +7005 +7006 +7007 +7008 +7009 +7010 +7011 +7012 +7013 +7014 +7015 +7016 +7017 +7018 +7019 +7020 +7021 +7022 +7023 +7024 +7025 +7026 +7027 +7028 +7029 +7030 +7031 +7032 +7033 +7034 +7035 +7036 +7037 +7038 +7039 +7040 +7041 +7042 +7043 +7044 +7045 +7046 +7047 +7048 +7049 +7050 +7051 +7052 +7053 +7054 +7055 +7056 +7057 +7058 +7059 +7060 +7061 +7062 +7063 +7064 +7065 +7066 +7067 +7068 +7069 +7070 +7071 +7072 +7073 +7074 +7075 +7076 +7077 +7078 +7079 +7080 +7081 +7082 +7083 +7084 +7085 +7086 +7087 +7088 +7089 +7090 +7091 +7092 +7093 +7094 +7095 +7096 +7097 +7098 +7099 +7100 +7101 +7102 +7103 +7104 +7105 +7106 +7107 +7108 +7109 +7110 +7111 +7112 +7113 +7114 +7115 +7116 +7117 +7118 +7119 +7120 +7121 +7122 +7123 +7124 +7125 +7126 +7127 +7128 +7129 +7130 +7131 +7132 +7133 +7134 +7135 +7136 +7137 +7138 +7139 +7140 +7141 +7142 +7143 +7144 +7145 +7146 +7147 +7148 +7149 +7150 +7151 +7152 +7153 +7154 +7155 +7156 +7157 +7158 +7159 +7160 +7161 +7162 +7163 +7164 +7165 +7166 +7167 +7168 +7169 +7170 +7171 +7172 +7173 +7174 +7175 +7176 +7177 +7178 +7179 +7180 +7181 +7182 +7183 +7184 +7185 +7186 +7187 +7188 +7189 +7190 +7191 +7192 +7193 +7194 +7195 +7196 +7197 +7198 +7199 +7200 +7201 +7202 +7203 +7204 +7205 +7206 +7207 +7208 +7209 +7210 +7211 +7212 +7213 +7214 +7215 +7216 +7217 +7218 +7219 +7220 +7221 +7222 +7223 +7224 +7225 +7226 +7227 +7228 +7229 +7230 +7231 +7232 +7233 +7234 +7235 +7236 +7237 +7238 +7239 +7240 +7241 +7242 +7243 +7244 +7245 +7246 +7247 +7248 +7249 +7250 +7251 +7252 +7253 +7254 +7255 +7256 +7257 +7258 +7259 +7260 +7261 +7262 +7263 +7264 +7265 +7266 +7267 +7268 +7269 +7270 +7271 +7272 +7273 +7274 +7275 +7276 +7277 +7278 +7279 +7280 +7281 +7282 +7283 +7284 +7285 +7286 +7287 +7288 +7289 +7290 +7291 +7292 +7293 +7294 +7295 +7296 +7297 +7298 +7299 +7300 +7301 +7302 +7303 +7304 +7305 +7306 +7307 +7308 +7309 +7310 +7311 +7312 +7313 +7314 +7315 +7316 +7317 +7318 +7319 +7320 +7321 +7322 +7323 +7324 +7325 +7326 +7327 +7328 +7329 +7330 +7331 +7332 +7333 +7334 +7335 +7336 +7337 +7338 +7339 +7340 +7341 +7342 +7343 +7344 +7345 +7346 +7347 +7348 +7349 +7350 +7351 +7352 +7353 +7354 +7355 +7356 +7357 +7358 +7359 +7360 +7361 +7362 +7363 +7364 +7365 +7366 +7367 +7368 +7369 +7370 +7371 +7372 +7373 +7374 +7375 +7376 +7377 +7378 +7379 +7380 +7381 +7382 +7383 +7384 +7385 +7386 +7387 +7388 +7389 +7390 +7391 +7392 +7393 +7394 +7395 +7396 +7397 +7398 +7399 +7400 +7401 +7402 +7403 +7404 +7405 +7406 +7407 +7408 +7409 +7410 +7411 +7412 +7413 +7414 +7415 +7416 +7417 +7418 +7419 +7420 +7421 +7422 +7423 +7424 +7425 +7426 +7427 +7428 +7429 +7430 +7431 +7432 +7433 +7434 +7435 +7436 +7437 +7438 +7439 +7440 +7441 +7442 +7443 +7444 +7445 +7446 +7447 +7448 +7449 +7450 +7451 +7452 +7453 +7454 +7455 +7456 +7457 +7458 +7459 +7460 +7461 +7462 +7463 +7464 +7465 +7466 +7467 +7468 +7469 +7470 +7471 +7472 +7473 +7474 +7475 +7476 +7477 +7478 +7479 +7480 +7481 +7482 +7483 +7484 +7485 +7486 +7487 +7488 +7489 +7490 +7491 +7492 +7493 +7494 +7495 +7496 +7497 +7498 +7499 +7500 +7501 +7502 +7503 +7504 +7505 +7506 +7507 +7508 +7509 +7510 +7511 +7512 +7513 +7514 +7515 +7516 +7517 +7518 +7519 +7520 +7521 +7522 +7523 +7524 +7525 +7526 +7527 +7528 +7529 +7530 +7531 +7532 +7533 +7534 +7535 +7536 +7537 +7538 +7539 +7540 +7541 +7542 +7543 +7544 +7545 +7546 +7547 +7548 +7549 +7550 +7551 +7552 +7553 +7554 +7555 +7556 +7557 +7558 +7559 +7560 +7561 +7562 +7563 +7564 +7565 +7566 +7567 +7568 +7569 +7570 +7571 +7572 +7573 +7574 +7575 +7576 +7577 +7578 +7579 +7580 +7581 +7582 +7583 +7584 +7585 +7586 +7587 +7588 +7589 +7590 +7591 +7592 +7593 +7594 +7595 +7596 +7597 +7598 +7599 +7600 +7601 +7602 +7603 +7604 +7605 +7606 +7607 +7608 +7609 +7610 +7611 +7612 +7613 +7614 +7615 +7616 +7617 +7618 +7619 +7620 +7621 +7622 +7623 +7624 +7625 +7626 +7627 +7628 +7629 +7630 +7631 +7632 +7633 +7634 +7635 +7636 +7637 +7638 +7639 +7640 +7641 +7642 +7643 +7644 +7645 +7646 +7647 +7648 +7649 +7650 +7651 +7652 +7653 +7654 +7655 +7656 +7657 +7658 +7659 +7660 +7661 +7662 +7663 +7664 +7665 +7666 +7667 +7668 +7669 +7670 +7671 +7672 +7673 +7674 +7675 +7676 +7677 +7678 +7679 +7680 +7681 +7682 +7683 +7684 +7685 +7686 +7687 +7688 +7689 +7690 +7691 +7692 +7693 +7694 +7695 +7696 +7697 +7698 +7699 +7700 +7701 +7702 +7703 +7704 +7705 +7706 +7707 +7708 +7709 +7710 +7711 +7712 +7713 +7714 +7715 +7716 +7717 +7718 +7719 +7720 +7721 +7722 +7723 +7724 +7725 +7726 +7727 +7728 +7729 +7730 +7731 +7732 +7733 +7734 +7735 +7736 +7737 +7738 +7739 +7740 +7741 +7742 +7743 +7744 +7745 +7746 +7747 +7748 +7749 +7750 +7751 +7752 +7753 +7754 +7755 +7756 +7757 +7758 +7759 +7760 +7761 +7762 +7763 +7764 +7765 +7766 +7767 +7768 +7769 +7770 +7771 +7772 +7773 +7774 +7775 +7776 +7777 +7778 +7779 +7780 +7781 +7782 +7783 +7784 +7785 +7786 +7787 +7788 +7789 +7790 +7791 +7792 +7793 +7794 +7795 +7796 +7797 +7798 +7799 +7800 +7801 +7802 +7803 +7804 +7805 +7806 +7807 +7808 +7809 +7810 +7811 +7812 +7813 +7814 +7815 +7816 +7817 +7818 +7819 +7820 +7821 +7822 +7823 +7824 +7825 +7826 +7827 +7828 +7829 +7830 +7831 +7832 +7833 +7834 +7835 +7836 +7837 +7838 +7839 +7840 +7841 +7842 +7843 +7844 +7845 +7846 +7847 +7848 +7849 +7850 +7851 +7852 +7853 +7854 +7855 +7856 +7857 +7858 +7859 +7860 +7861 +7862 +7863 +7864 +7865 +7866 +7867 +7868 +7869 +7870 +7871 +7872 +7873 +7874 +7875 +7876 +7877 +7878 +7879 +7880 +7881 +7882 +7883 +7884 +7885 +7886 +7887 +7888 +7889 +7890 +7891 +7892 +7893 +7894 +7895 +7896 +7897 +7898 +7899 +7900 +7901 +7902 +7903 +7904 +7905 +7906 +7907 +7908 +7909 +7910 +7911 +7912 +7913 +7914 +7915 +7916 +7917 +7918 +7919 +7920 +7921 +7922 +7923 +7924 +7925 +7926 +7927 +7928 +7929 +7930 +7931 +7932 +7933 +7934 +7935 +7936 +7937 +7938 +7939 +7940 +7941 +7942 +7943 +7944 +7945 +7946 +7947 +7948 +7949 +7950 +7951 +7952 +7953 +7954 +7955 +7956 +7957 +7958 +7959 +7960 +7961 +7962 +7963 +7964 +7965 +7966 +7967 +7968 +7969 +7970 +7971 +7972 +7973 +7974 +7975 +7976 +7977 +7978 +7979 +7980 +7981 +7982 +7983 +7984 +7985 +7986 +7987 +7988 +7989 +7990 +7991 +7992 +7993 +7994 +7995 +7996 +7997 +7998 +7999 +8000 +8001 +8002 +8003 +8004 +8005 +8006 +8007 +8008 +8009 +8010 +8011 +8012 +8013 +8014 +8015 +8016 +8017 +8018 +8019 +8020 +8021 +8022 +8023 +8024 +8025 +8026 +8027 +8028 +8029 +8030 +8031 +8032 +8033 +8034 +8035 +8036 +8037 +8038 +8039 +8040 +8041 +8042 +8043 +8044 +8045 +8046 +8047 +8048 +8049 +8050 +8051 +8052 +8053 +8054 +8055 +8056 +8057 +8058 +8059 +8060 +8061 +8062 +8063 +8064 +8065 +8066 +8067 +8068 +8069 +8070 +8071 +8072 +8073 +8074 +8075 +8076 +8077 +8078 +8079 +8080 +8081 +8082 +8083 +8084 +8085 +8086 +8087 +8088 +8089 +8090 +8091 +8092 +8093 +8094 +8095 +8096 +8097 +8098 +8099 +8100 +8101 +8102 +8103 +8104 +8105 +8106 +8107 +8108 +8109 +8110 +8111 +8112 +8113 +8114 +8115 +8116 +8117 +8118 +8119 +8120 +8121 +8122 +8123 +8124 +8125 +8126 +8127 +8128 +8129 +8130 +8131 +8132 +8133 +8134 +8135 +8136 +8137 +8138 +8139 +8140 +8141 +8142 +8143 +8144 +8145 +8146 +8147 +8148 +8149 +8150 +8151 +8152 +8153 +8154 +8155 +8156 +8157 +8158 +8159 +8160 +8161 +8162 +8163 +8164 +8165 +8166 +8167 +8168 +8169 +8170 +8171 +8172 +8173 +8174 +8175 +8176 +8177 +8178 +8179 +8180 +8181 +8182 +8183 +8184 +8185 +8186 +8187 +8188 +8189 +8190 +8191 +8192 +8193 +8194 +8195 +8196 +8197 +8198 +8199 +8200 +8201 +8202 +8203 +8204 +8205 +8206 +8207 +8208 +8209 +8210 +8211 +8212 +8213 +8214 +8215 +8216 +8217 +8218 +8219 +8220 +8221 +8222 +8223 +8224 +8225 +8226 +8227 +8228 +8229 +8230 +8231 +8232 +8233 +8234 +8235 +8236 +8237 +8238 +8239 +8240 +8241 +8242 +8243 +8244 +8245 +8246 +8247 +8248 +8249 +8250 +8251 +8252 +8253 +8254 +8255 +8256 +8257 +8258 +8259 +8260 +8261 +8262 +8263 +8264 +8265 +8266 +8267 +8268 +8269 +8270 +8271 +8272 +8273 +8274 +8275 +8276 +8277 +8278 +8279 +8280 +8281 +8282 +8283 +8284 +8285 +8286 +8287 +8288 +8289 +8290 +8291 +8292 +8293 +8294 +8295 +8296 +8297 +8298 +8299 +8300 +8301 +8302 +8303 +8304 +8305 +8306 +8307 +8308 +8309 +8310 +8311 +8312 +8313 +8314 +8315 +8316 +8317 +8318 +8319 +8320 +8321 +8322 +8323 +8324 +8325 +8326 +8327 +8328 +8329 +8330 +8331 +8332 +8333 +8334 +8335 +8336 +8337 +8338 +8339 +8340 +8341 +8342 +8343 +8344 +8345 +8346 +8347 +8348 +8349 +8350 +8351 +8352 +8353 +8354 +8355 +8356 +8357 +8358 +8359 +8360 +8361 +8362 +8363 +8364 +8365 +8366 +8367 +8368 +8369 +8370 +8371 +8372 +8373 +8374 +8375 +8376 +8377 +8378 +8379 +8380 +8381 +8382 +8383 +8384 +8385 +8386 +8387 +8388 +8389 +8390 +8391 +8392 +8393 +8394 +8395 +8396 +8397 +8398 +8399 +8400 +8401 +8402 +8403 +8404 +8405 +8406 +8407 +8408 +8409 +8410 +8411 +8412 +8413 +8414 +8415 +8416 +8417 +8418 +8419 +8420 +8421 +8422 +8423 +8424 +8425 +8426 +8427 +8428 +8429 +8430 +8431 +8432 +8433 +8434 +8435 +8436 +8437 +8438 +8439 +8440 +8441 +8442 +8443 +8444 +8445 +8446 +8447 +8448 +8449 +8450 +8451 +8452 +8453 +8454 +8455 +8456 +8457 +8458 +8459 +8460 +8461 +8462 +8463 +8464 +8465 +8466 +8467 +8468 +8469 +8470 +8471 +8472 +8473 +8474 +8475 +8476 +8477 +8478 +8479 +8480 +8481 +8482 +8483 +8484 +8485 +8486 +8487 +8488 +8489 +8490 +8491 +8492 +8493 +8494 +8495 +8496 +8497 +8498 +8499 +8500 +8501 +8502 +8503 +8504 +8505 +8506 +8507 +8508 +8509 +8510 +8511 +8512 +8513 +8514 +8515 +8516 +8517 +8518 +8519 +8520 +8521 +8522 +8523 +8524 +8525 +8526 +8527 +8528 +8529 +8530 +8531 +8532 +8533 +8534 +8535 +8536 +8537 +8538 +8539 +8540 +8541 +8542 +8543 +8544 +8545 +8546 +8547 +8548 +8549 +8550 +8551 +8552 +8553 +8554 +8555 +8556 +8557 +8558 +8559 +8560 +8561 +8562 +8563 +8564 +8565 +8566 +8567 +8568 +8569 +8570 +8571 +8572 +8573 +8574 +8575 +8576 +8577 +8578 +8579 +8580 +8581 +8582 +8583 +8584 +8585 +8586 +8587 +8588 +8589 +8590 +8591 +8592 +8593 +8594 +8595 +8596 +8597 +8598 +8599 +8600 +8601 +8602 +8603 +8604 +8605 +8606 +8607 +8608 +8609 +8610 +8611 +8612 +8613 +8614 +8615 +8616 +8617 +8618 +8619 +8620 +8621 +8622 +8623 +8624 +8625 +8626 +8627 +8628 +8629 +8630 +8631 +8632 +8633 +8634 +8635 +8636 +8637 +8638 +8639 +8640 +8641 +8642 +8643 +8644 +8645 +8646 +8647 +8648 +8649 +8650 +8651 +8652 +8653 +8654 +8655 +8656 +8657 +8658 +8659 +8660 +8661 +8662 +8663 +8664 +8665 +8666 +8667 +8668 +8669 +8670 +8671 +8672 +8673 +8674 +8675 +8676 +8677 +8678 +8679 +8680 +8681 +8682 +8683 +8684 +8685 +8686 +8687 +8688 +8689 +8690 +8691 +8692 +8693 +8694 +8695 +8696 +8697 +8698 +8699 +8700 +8701 +8702 +8703 +8704 +8705 +8706 +8707 +8708 +8709 +8710 +8711 +8712 +8713 +8714 +8715 +8716 +8717 +8718 +8719 +8720 +8721 +8722 +8723 +8724 +8725 +8726 +8727 +8728 +8729 +8730 +8731 +8732 +8733 +8734 +8735 +8736 +8737 +8738 +8739 +8740 +8741 +8742 +8743 +8744 +8745 +8746 +8747 +8748 +8749 +8750 +8751 +8752 +8753 +8754 +8755 +8756 +8757 +8758 +8759 +8760 +8761 +8762 +8763 +8764 +8765 +8766 +8767 +8768 +8769 +8770 +8771 +8772 +8773 +8774 +8775 +8776 +8777 +8778 +8779 +8780 +8781 +8782 +8783 +8784 +8785 +8786 +8787 +8788 +8789 +8790 +8791 +8792 +8793 +8794 +8795 +8796 +8797 +8798 +8799 +8800 +8801 +8802 +8803 +8804 +8805 +8806 +8807 +8808 +8809 +8810 +8811 +8812 +8813 +8814 +8815 +8816 +8817 +8818 +8819 +8820 +8821 +8822 +8823 +8824 +8825 +8826 +8827 +8828 +8829 +8830 +8831 +8832 +8833 +8834 +8835 +8836 +8837 +8838 +8839 +8840 +8841 +8842 +8843 +8844 +8845 +8846 +8847 +8848 +8849 +8850 +8851 +8852 +8853 +8854 +8855 +8856 +8857 +8858 +8859 +8860 +8861 +8862 +8863 +8864 +8865 +8866 +8867 +8868 +8869 +8870 +8871 +8872 +8873 +8874 +8875 +8876 +8877 +8878 +8879 +8880 +8881 +8882 +8883 +8884 +8885 +8886 +8887 +8888 +8889 +8890 +8891 +8892 +8893 +8894 +8895 +8896 +8897 +8898 +8899 +8900 +8901 +8902 +8903 +8904 +8905 +8906 +8907 +8908 +8909 +8910 +8911 +8912 +8913 +8914 +8915 +8916 +8917 +8918 +8919 +8920 +8921 +8922 +8923 +8924 +8925 +8926 +8927 +8928 +8929 +8930 +8931 +8932 +8933 +8934 +8935 +8936 +8937 +8938 +8939 +8940 +8941 +8942 +8943 +8944 +8945 +8946 +8947 +8948 +8949 +8950 +8951 +8952 +8953 +8954 +8955 +8956 +8957 +8958 +8959 +8960 +8961 +8962 +8963 +8964 +8965 +8966 +8967 +8968 +8969 +8970 +8971 +8972 +8973 +8974 +8975 +8976 +8977 +8978 +8979 +8980 +8981 +8982 +8983 +8984 +8985 +8986 +8987 +8988 +8989 +8990 +8991 +8992 +8993 +8994 +8995 +8996 +8997 +8998 +8999 +9000 +9001 +9002 +9003 +9004 +9005 +9006 +9007 +9008 +9009 +9010 +9011 +9012 +9013 +9014 +9015 +9016 +9017 +9018 +9019 +9020 +9021 +9022 +9023 +9024 +9025 +9026 +9027 +9028 +9029 +9030 +9031 +9032 +9033 +9034 +9035 +9036 +9037 +9038 +9039 +9040 +9041 +9042 +9043 +9044 +9045 +9046 +9047 +9048 +9049 +9050 +9051 +9052 +9053 +9054 +9055 +9056 +9057 +9058 +9059 +9060 +9061 +9062 +9063 +9064 +9065 +9066 +9067 +9068 +9069 +9070 +9071 +9072 +9073 +9074 +9075 +9076 +9077 +9078 +9079 +9080 +9081 +9082 +9083 +9084 +9085 +9086 +9087 +9088 +9089 +9090 +9091 +9092 +9093 +9094 +9095 +9096 +9097 +9098 +9099 +9100 +9101 +9102 +9103 +9104 +9105 +9106 +9107 +9108 +9109 +9110 +9111 +9112 +9113 +9114 +9115 +9116 +9117 +9118 +9119 +9120 +9121 +9122 +9123 +9124 +9125 +9126 +9127 +9128 +9129 +9130 +9131 +9132 +9133 +9134 +9135 +9136 +9137 +9138 +9139 +9140 +9141 +9142 +9143 +9144 +9145 +9146 +9147 +9148 +9149 +9150 +9151 +9152 +9153 +9154 +9155 +9156 +9157 +9158 +9159 +9160 +9161 +9162 +9163 +9164 +9165 +9166 +9167 +9168 +9169 +9170 +9171 +9172 +9173 +9174 +9175 +9176 +9177 +9178 +9179 +9180 +9181 +9182 +9183 +9184 +9185 +9186 +9187 +9188 +9189 +9190 +9191 +9192 +9193 +9194 +9195 +9196 +9197 +9198 +9199 +9200 +9201 +9202 +9203 +9204 +9205 +9206 +9207 +9208 +9209 +9210 +9211 +9212 +9213 +9214 +9215 +9216 +9217 +9218 +9219 +9220 +9221 +9222 +9223 +9224 +9225 +9226 +9227 +9228 +9229 +9230 +9231 +9232 +9233 +9234 +9235 +9236 +9237 +9238 +9239 +9240 +9241 +9242 +9243 +9244 +9245 +9246 +9247 +9248 +9249 +9250 +9251 +9252 +9253 +9254 +9255 +9256 +9257 +9258 +9259 +9260 +9261 +9262 +9263 +9264 +9265 +9266 +9267 +9268 +9269 +9270 +9271 +9272 +9273 +9274 +9275 +9276 +9277 +9278 +9279 +9280 +9281 +9282 +9283 +9284 +9285 +9286 +9287 +9288 +9289 +9290 +9291 +9292 +9293 +9294 +9295 +9296 +9297 +9298 +9299 +9300 +9301 +9302 +9303 +9304 +9305 +9306 +9307 +9308 +9309 +9310 +9311 +9312 +9313 +9314 +9315 +9316 +9317 +9318 +9319 +9320 +9321 +9322 +9323 +9324 +9325 +9326 +9327 +9328 +9329 +9330 +9331 +9332 +9333 +9334 +9335 +9336 +9337 +9338 +9339 +9340 +9341 +9342 +9343 +9344 +9345 +9346 +9347 +9348 +9349 +9350 +9351 +9352 +9353 +9354 +9355 +9356 +9357 +9358 +9359 +9360 +9361 +9362 +9363 +9364 +9365 +9366 +9367 +9368 +9369 +9370 +9371 +9372 +9373 +9374 +9375 +9376 +9377 +9378 +9379 +9380 +9381 +9382 +9383 +9384 +9385 +9386 +9387 +9388 +9389 +9390 +9391 +9392 +9393 +9394 +9395 +9396 +9397 +9398 +9399 +9400 +9401 +9402 +9403 +9404 +9405 +9406 +9407 +9408 +9409 +9410 +9411 +9412 +9413 +9414 +9415 +9416 +9417 +9418 +9419 +9420 +9421 +9422 +9423 +9424 +9425 +9426 +9427 +9428 +9429 +9430 +9431 +9432 +9433 +9434 +9435 +9436 +9437 +9438 +9439 +9440 +9441 +9442 +9443 +9444 +9445 +9446 +9447 +9448 +9449 +9450 +9451 +9452 +9453 +9454 +9455 +9456 +9457 +9458 +9459 +9460 +9461 +9462 +9463 +9464 +9465 +9466 +9467 +9468 +9469 +9470 +9471 +9472 +9473 +9474 +9475 +9476 +9477 +9478 +9479 +9480 +9481 +9482 +9483 +9484 +9485 +9486 +9487 +9488 +9489 +9490 +9491 +9492 +9493 +9494 +9495 +9496 +9497 +9498 +9499 +9500 +9501 +9502 +9503 +9504 +9505 +9506 +9507 +9508 +9509 +9510 +9511 +9512 +9513 +9514 +9515 +9516 +9517 +9518 +9519 +9520 +9521 +9522 +9523 +9524 +9525 +9526 +9527 +9528 +9529 +9530 +9531 +9532 +9533 +9534 +9535 +9536 +9537 +9538 +9539 +9540 +9541 +9542 +9543 +9544 +9545 +9546 +9547 +9548 +9549 +9550 +9551 +9552 +9553 +9554 +9555 +9556 +9557 +9558 +9559 +9560 +9561 +9562 +9563 +9564 +9565 +9566 +9567 +9568 +9569 +9570 +9571 +9572 +9573 +9574 +9575 +9576 +9577 +9578 +9579 +9580 +9581 +9582 +9583 +9584 +9585 +9586 +9587 +9588 +9589 +9590 +9591 +9592 +9593 +9594 +9595 +9596 +9597 +9598 +9599 +9600 +9601 +9602 +9603 +9604 +9605 +9606 +9607 +9608 +9609 +9610 +9611 +9612 +9613 +9614 +9615 +9616 +9617 +9618 +9619 +9620 +9621 +9622 +9623 +9624 +9625 +9626 +9627 +9628 +9629 +9630 +9631 +9632 +9633 +9634 +9635 +9636 +9637 +9638 +9639 +9640 +9641 +9642 +9643 +9644 +9645 +9646 +9647 +9648 +9649 +9650 +9651 +9652 +9653 +9654 +9655 +9656 +9657 +9658 +9659 +9660 +9661 +9662 +9663 +9664 +9665 +9666 +9667 +9668 +9669 +9670 +9671 +9672 +9673 +9674 +9675 +9676 +9677 +9678 +9679 +9680 +9681 +9682 +9683 +9684 +9685 +9686 +9687 +9688 +9689 +9690 +9691 +9692 +9693 +9694 +9695 +9696 +9697 +9698 +9699 +9700 +9701 +9702 +9703 +9704 +9705 +9706 +9707 +9708 +9709 +9710 +9711 +9712 +9713 +9714 +9715 +9716 +9717 +9718 +9719 +9720 +9721 +9722 +9723 +9724 +9725 +9726 +9727 +9728 +9729 +9730 +9731 +9732 +9733 +9734 +9735 +9736 +9737 +9738 +9739 +9740 +9741 +9742 +9743 +9744 +9745 +9746 +9747 +9748 +9749 +9750 +9751 +9752 +9753 +9754 +9755 +9756 +9757 +9758 +9759 +9760 +9761 +9762 +9763 +9764 +9765 +9766 +9767 +9768 +9769 +9770 +9771 +9772 +9773 +9774 +9775 +9776 +9777 +9778 +9779 +9780 +9781 +9782 +9783 +9784 +9785 +9786 +9787 +9788 +9789 +9790 +9791 +9792 +9793 +9794 +9795 +9796 +9797 +9798 +9799 +9800 +9801 +9802 +9803 +9804 +9805 +9806 +9807 +9808 +9809 +9810 +9811 +9812 +9813 +9814 +9815 +9816 +9817 +9818 +9819 +9820 +9821 +9822 +9823 +9824 +9825 +9826 +9827 +9828 +9829 +9830 +9831 +9832 +9833 +9834 +9835 +9836 +9837 +9838 +9839 +9840 +9841 +9842 +9843 +9844 +9845 +9846 +9847 +9848 +9849 +9850 +9851 +9852 +9853 +9854 +9855 +9856 +9857 +9858 +9859 +9860 +9861 +9862 +9863 +9864 +9865 +9866 +9867 +9868 +9869 +9870 +9871 +9872 +9873 +9874 +9875 +9876 +9877 +9878 +9879 +9880 +9881 +9882 +9883 +9884 +9885 +9886 +9887 +9888 +9889 +9890 +9891 +9892 +9893 +9894 +9895 +9896 +9897 +9898 +9899 +9900 +9901 +9902 +9903 +9904 +9905 +9906 +9907 +9908 +9909 +9910 +9911 +9912 +9913 +9914 +9915 +9916 +9917 +9918 +9919 +9920 +9921 +9922 +9923 +9924 +9925 +9926 +9927 +9928 +9929 +9930 +9931 +9932 +9933 +9934 +9935 +9936 +9937 +9938 +9939 +9940 +9941 +9942 +9943 +9944 +9945 +9946 +9947 +9948 +9949 +9950 +9951 +9952 +9953 +9954 +9955 +9956 +9957 +9958 +9959 +9960 +9961 +9962 +9963 +9964 +9965 +9966 +9967 +9968 +9969 +9970 +9971 +9972 +9973 +9974 +9975 +9976 +9977 +9978 +9979 +9980 +9981 +9982 +9983 +9984 +9985 +9986 +9987 +9988 +9989 +9990 +9991 +9992 +9993 +9994 +9995 +9996 +9997 +9998 +9999 diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml new file mode 100644 index 0000000000..059075318a --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + consumermodule + jar + 1.0 + + + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java new file mode 100644 index 0000000000..c4b5eed011 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.consumermodule; + +import com.baeldung.servicemodule.external.TextService; +import com.baeldung.servicemodule.external.TextServiceFactory; + +public class Application { + + public static void main(String args[]) { + TextService textService = TextServiceFactory.getTextService("lowercase"); + System.out.println(textService.processText("Hello from Baeldung!")); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..c02e6e6522 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/consumermodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.consumermodule { + requires com.baeldung.servicemodule; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml new file mode 100644 index 0000000000..282723e0a0 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + pom + + + servicemodule + consumermodule + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + + + UTF-8 + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml new file mode 100644 index 0000000000..1bda70f867 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.baeldung.servicemodule + servicemodule + jar + + + com.baeldung.decoupling-pattern1 + decoupling-pattern1 + 1.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java new file mode 100644 index 0000000000..2b9f0dce50 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextService.java @@ -0,0 +1,7 @@ +package com.baeldung.servicemodule.external; + +public interface TextService { + + String processText(String text); + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java new file mode 100644 index 0000000000..4611bc1c8c --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/external/TextServiceFactory.java @@ -0,0 +1,14 @@ +package com.baeldung.servicemodule.external; + +import com.baeldung.servicemodule.internal.LowercaseTextService; +import com.baeldung.servicemodule.internal.UppercaseTextService; + +public class TextServiceFactory { + + private TextServiceFactory() {} + + public static TextService getTextService(String name) { + return name.equalsIgnoreCase("lowercase") ? new LowercaseTextService(): new UppercaseTextService(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java new file mode 100644 index 0000000000..e2d98f609e --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/LowercaseTextService.java @@ -0,0 +1,12 @@ +package com.baeldung.servicemodule.internal; + +import com.baeldung.servicemodule.external.TextService; + +public class LowercaseTextService implements TextService { + + @Override + public String processText(String text) { + return text.toLowerCase(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java new file mode 100644 index 0000000000..c94da2a8a5 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/com/baeldung/servicemodule/internal/UppercaseTextService.java @@ -0,0 +1,12 @@ +package com.baeldung.servicemodule.internal; + +import com.baeldung.servicemodule.external.TextService; + +public class UppercaseTextService implements TextService { + + @Override + public String processText(String text) { + return text.toUpperCase(); + } + +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java new file mode 100644 index 0000000000..230b659aa9 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/servicemodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.servicemodule { + exports com.baeldung.servicemodule.external; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml new file mode 100644 index 0000000000..757d9229df --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.baeldung.consumermodule + consumermodule + 1.0 + + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + com.baeldung.providermodule + providermodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java new file mode 100644 index 0000000000..b9430eb458 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/com/baeldung/consumermodule/Application.java @@ -0,0 +1,15 @@ +package com.baeldung.consumermodule; + +import com.baeldung.servicemodule.TextService; + +import java.util.ServiceLoader; + +public class Application { + + public static void main(String[] args) { + ServiceLoader services = ServiceLoader.load(TextService.class); + for (final TextService service: services) { + System.out.println("The service " + service.getClass().getSimpleName() + " says: " + service.parseText("Hello from Baeldung!")); + } + } +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..d8438a7bbc --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.consumermodule { + requires com.baeldung.servicemodule; + uses com.baeldung.servicemodule.TextService; +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml new file mode 100644 index 0000000000..f8c05d40b8 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + pom + + + servicemodule + providermodule + consumermodule + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml new file mode 100644 index 0000000000..ceeda9049c --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + com.baeldung.providermodule + providermodule + 1.0 + + + com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java new file mode 100644 index 0000000000..51e742e641 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/com/baeldung/providermodule/LowercaseTextService.java @@ -0,0 +1,10 @@ +package com.baeldung.providermodule; + +import com.baeldung.servicemodule.TextService; + +public class LowercaseTextService implements TextService { + @Override + public String parseText(String text) { + return text.toLowerCase(); + } +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java new file mode 100644 index 0000000000..1223aa0121 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.providermodule { + requires com.baeldung.servicemodule; + provides com.baeldung.servicemodule.TextService with com.baeldung.providermodule.LowercaseTextService; +} \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml new file mode 100644 index 0000000000..4de3df8c01 --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + >com.baeldung.decoupling-pattern2 + decoupling-pattern2 + 1.0-SNAPSHOT + + + com.baeldung.servicemodule + servicemodule + 1.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java new file mode 100644 index 0000000000..dedbd774ca --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/com/baeldung/servicemodule/TextService.java @@ -0,0 +1,6 @@ +package com.baeldung.servicemodule; + +public interface TextService { + + String parseText(String text); +} diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java new file mode 100644 index 0000000000..dbd70b944b --- /dev/null +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.servicemodule { + exports com.baeldung.servicemodule; +} \ No newline at end of file diff --git a/core-java-modules/core-java-jvm/README.md b/core-java-modules/core-java-jvm/README.md new file mode 100644 index 0000000000..82067ad952 --- /dev/null +++ b/core-java-modules/core-java-jvm/README.md @@ -0,0 +1,6 @@ +========= + +## Core Java JVM Cookbooks and Examples + +### Relevant Articles: +- [Method Inlining in the JVM](https://www.baeldung.com/jvm-method-inlining) diff --git a/core-java-modules/core-java-jvm/pom.xml b/core-java-modules/core-java-jvm/pom.xml new file mode 100644 index 0000000000..6c700cd005 --- /dev/null +++ b/core-java-modules/core-java-jvm/pom.xml @@ -0,0 +1,41 @@ + + 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-modules/core-java-jvm/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java b/core-java-modules/core-java-jvm/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java new file mode 100644 index 0000000000..7de642f1c0 --- /dev/null +++ b/core-java-modules/core-java-jvm/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-modules/core-java-jvm/src/main/java/com/baeldung/inlining/InliningExample.java b/core-java-modules/core-java-jvm/src/main/java/com/baeldung/inlining/InliningExample.java new file mode 100644 index 0000000000..4c1802d0e4 --- /dev/null +++ b/core-java-modules/core-java-jvm/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-modules/core-java-jvm/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java new file mode 100644 index 0000000000..8e4b0353e6 --- /dev/null +++ b/core-java-modules/core-java-jvm/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; + } +} diff --git a/core-java-modules/core-java-lambdas/pom.xml b/core-java-modules/core-java-lambdas/pom.xml new file mode 100644 index 0000000000..d6158c2946 --- /dev/null +++ b/core-java-modules/core-java-lambdas/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + core-java-lambdas + 0.1.0-SNAPSHOT + core-java + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java new file mode 100644 index 0000000000..5c1201150f --- /dev/null +++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java @@ -0,0 +1,88 @@ +package com.baeldung.lambdas; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +/** + * Class with examples about working with capturing lambdas. + */ +public class LambdaVariables { + + private volatile boolean run = true; + private int start = 0; + + private ExecutorService executor = Executors.newFixedThreadPool(3); + + public static void main(String[] args) { + new LambdaVariables().localVariableMultithreading(); + } + + Supplier incrementer(int start) { + return () -> start; // can't modify start parameter inside the lambda + } + + Supplier incrementer() { + return () -> start++; + } + + public void localVariableMultithreading() { + boolean run = true; + executor.execute(() -> { + while (run) { + // do operation + } + }); + // commented because it doesn't compile, it's just an example of non-final local variables in lambdas + // run = false; + } + + public void instanceVariableMultithreading() { + executor.execute(() -> { + while (run) { + // do operation + } + }); + + run = false; + } + + /** + * WARNING: always avoid this workaround!! + */ + public void workaroundSingleThread() { + int[] holder = new int[] { 2 }; + IntStream sums = IntStream + .of(1, 2, 3) + .map(val -> val + holder[0]); + + holder[0] = 0; + + System.out.println(sums.sum()); + } + + /** + * WARNING: always avoid this workaround!! + */ + public void workaroundMultithreading() { + int[] holder = new int[] { 2 }; + Runnable runnable = () -> System.out.println(IntStream + .of(1, 2, 3) + .map(val -> val + holder[0]) + .sum()); + + new Thread(runnable).start(); + + // simulating some processing + try { + Thread.sleep(new Random().nextInt(3) * 1000L); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + holder[0] = 0; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/.gitignore b/core-java-modules/core-java-lang-oop-2/.gitignore new file mode 100644 index 0000000000..36aba1c242 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/.gitignore @@ -0,0 +1,4 @@ +target/ +.idea/ +bin/ +*.iml \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-2/README.md b/core-java-modules/core-java-lang-oop-2/README.md new file mode 100644 index 0000000000..72c3c6742b --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/README.md @@ -0,0 +1,9 @@ +========= + +## Core Java Lang OOP 2 Cookbooks and Examples + +### Relevant Articles: +- [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors) +- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error) +- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes) +- [Raw Types in Java](https://www.baeldung.com/raw-types-java) diff --git a/core-java-modules/core-java-lang-oop-2/pom.xml b/core-java-modules/core-java-lang-oop-2/pom.xml new file mode 100644 index 0000000000..669a37b0f5 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + com.baeldung + core-java-lang-oop-2 + 0.1.0-SNAPSHOT + core-java-lang-oop-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + core-java-lang-oop-2 + + + src/main/resources + true + + + + + diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java new file mode 100644 index 0000000000..964156e8e4 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java @@ -0,0 +1,15 @@ +package com.baeldung.anonymous; + +public class Book { + + final String title; + + public Book(String title) { + this.title = title; + } + + public String description() { + return "Title: " + title; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java new file mode 100644 index 0000000000..d4eed69567 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java @@ -0,0 +1,64 @@ +package com.baeldung.anonymous; + +import java.util.ArrayList; +import java.util.List; + +/** + * Code snippet that illustrates the usage of anonymous classes. + * + * Note that use of Runnable instances in this example does not demonstrate their + * common use. + * + * @author A. Shcherbakov + * + */ +public class Main { + + public static void main(String[] args) { + final List actions = new ArrayList(2); + + Runnable action = new Runnable() { + @Override + public void run() { + System.out.println("Hello from runnable."); + } + + }; + actions.add(action); + + Book book = new Book("Design Patterns") { + @Override + public String description() { + return "Famous GoF book."; + } + }; + + System.out.println(String.format("Title: %s, description: %s", book.title, book.description())); + + actions.add(new Runnable() { + @Override + public void run() { + System.out.println("Hello from runnable #2."); + + } + }); + + int count = 1; + + Runnable action2 = new Runnable() { + static final int x = 0; + // static int y = 0; + + @Override + public void run() { + System.out.println(String.format("Runnable with captured variables: count = %s, x = %s", count, x)); + } + }; + actions.add(action2); + + for (Runnable a : actions) { + a.run(); + } + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java new file mode 100644 index 0000000000..07759ca9ba --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java @@ -0,0 +1,38 @@ +package com.baeldung.generics; + +import java.io.Serializable; + +public class Entry { + private String data; + private int rank; + + // non-generic constructor + public Entry(String data, int rank) { + this.data = data; + this.rank = rank; + } + + // generic constructor + public Entry(E element) { + this.data = element.toString(); + this.rank = element.getRank(); + } + + // getters and setters + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public int getRank() { + return rank; + } + + public void setRank(int rank) { + this.rank = rank; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java new file mode 100644 index 0000000000..27d3a44069 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java @@ -0,0 +1,53 @@ +package com.baeldung.generics; + +import java.io.Serializable; +import java.util.Optional; + +public class GenericEntry { + private T data; + private int rank; + + // non-generic constructor + public GenericEntry(int rank) { + this.rank = rank; + } + + // generic constructor + public GenericEntry(T data, int rank) { + this.data = data; + this.rank = rank; + } + + // generic constructor with different type + public GenericEntry(E element) { + this.data = (T) element; + this.rank = element.getRank(); + } + + // generic constructor with different type and wild card + public GenericEntry(Optional optional) { + if (optional.isPresent()) { + this.data = (T) optional.get(); + this.rank = optional.get() + .getRank(); + } + } + + // getters and setters + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public int getRank() { + return rank; + } + + public void setRank(int rank) { + this.rank = rank; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java new file mode 100644 index 0000000000..3d626b2fa5 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java @@ -0,0 +1,34 @@ +package com.baeldung.generics; + +public class MapEntry { + private K key; + private V value; + + public MapEntry() { + super(); + } + + // generic constructor with two parameters + public MapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + // getters and setters + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java new file mode 100644 index 0000000000..bfc9f63071 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java @@ -0,0 +1,50 @@ +package com.baeldung.generics; + +import java.io.Serializable; + +public class Product implements Rankable, Serializable { + private String name; + private double price; + private int sales; + + public Product(String name, double price) { + this.name = name; + this.price = price; + } + + @Override + public int getRank() { + return sales; + } + + @Override + public String toString() { + return "Product [name=" + name + ", price=" + price + ", sales=" + sales + "]"; + } + + // getters and setters + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public int getSales() { + return sales; + } + + public void setSales(int sales) { + this.sales = sales; + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java new file mode 100644 index 0000000000..72bda67d9d --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java @@ -0,0 +1,5 @@ +package com.baeldung.generics; + +public interface Rankable { + public int getRank(); +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java new file mode 100644 index 0000000000..e358219d24 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java @@ -0,0 +1,25 @@ +package com.baeldung.rawtype; + +import java.util.ArrayList; +import java.util.List; + +public class RawTypeDemo { + + public static void main(String[] args) { + RawTypeDemo rawTypeDemo = new RawTypeDemo(); + rawTypeDemo.methodA(); + } + + public void methodA() { + // parameterized type + List listStr = new ArrayList<>(); + listStr.add("Hello Folks!"); + methodB(listStr); + String s = listStr.get(1); // ClassCastException at run time + } + + public void methodB(List rawList) { // Inexpressive raw type + rawList.add(1); // Unsafe operation + } + +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClass.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClass.java new file mode 100644 index 0000000000..ccf8646f57 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClass.java @@ -0,0 +1,16 @@ +package com.baeldung.supertypecompilerexception; + +public class MyClass { + + private int myField1 = 10; + private int myField2; + + public MyClass() { + //uncomment this to see the supertype compiler error: + //this(myField1); + } + + public MyClass(int i) { + myField2 = i; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution1.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution1.java new file mode 100644 index 0000000000..36fa446302 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution1.java @@ -0,0 +1,15 @@ +package com.baeldung.supertypecompilerexception; + +public class MyClassSolution1 { + + private int myField1 = 10; + private int myField2; + + public MyClassSolution1() { + myField2 = myField1; + } + + public MyClassSolution1(int i) { + myField2 = i; + } +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution2.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution2.java new file mode 100644 index 0000000000..adaea4bfbe --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution2.java @@ -0,0 +1,19 @@ +package com.baeldung.supertypecompilerexception; + +public class MyClassSolution2 { + + private int myField1 = 10; + private int myField2; + + public MyClassSolution2() { + setupMyFields(myField1); + } + + public MyClassSolution2(int i) { + setupMyFields(i); + } + + private void setupMyFields(int i) { + myField2 = i; + } +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution3.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution3.java new file mode 100644 index 0000000000..04048f01db --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyClassSolution3.java @@ -0,0 +1,15 @@ +package com.baeldung.supertypecompilerexception; + +public class MyClassSolution3 { + + private static final int SOME_CONSTANT = 10; + private int myField2; + + public MyClassSolution3() { + this(SOME_CONSTANT); + } + + public MyClassSolution3(int i) { + myField2 = i; + } +} diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyException.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyException.java new file mode 100644 index 0000000000..db60deb83f --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/supertypecompilerexception/MyException.java @@ -0,0 +1,14 @@ +package com.baeldung.supertypecompilerexception; + +public class MyException extends RuntimeException { + private int errorCode = 0; + + public MyException(String message) { + //uncomment this to see the supertype compiler error: + //super(message + getErrorCode()); + } + + public int getErrorCode() { + return errorCode; + } +} diff --git a/core-java-modules/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java b/core-java-modules/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java new file mode 100644 index 0000000000..60907bbfd3 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.generics; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.Serializable; +import java.util.Optional; + +import org.junit.Test; + +public class GenericConstructorUnitTest { + + @Test + public void givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK() { + Entry entry = new Entry("sample", 1); + + assertEquals("sample", entry.getData()); + assertEquals(1, entry.getRank()); + } + + @Test + public void givenGenericConstructor_whenCreateNonGenericEntry_thenOK() { + Product product = new Product("milk", 2.5); + product.setSales(30); + Entry entry = new Entry(product); + + assertEquals(product.toString(), entry.getData()); + assertEquals(30, entry.getRank()); + } + + @Test + public void givenNonGenericConstructor_whenCreateGenericEntry_thenOK() { + GenericEntry entry = new GenericEntry(1); + + assertNull(entry.getData()); + assertEquals(1, entry.getRank()); + } + + @Test + public void givenGenericConstructor_whenCreateGenericEntry_thenOK() { + GenericEntry entry = new GenericEntry("sample", 1); + + assertEquals("sample", entry.getData()); + assertEquals(1, entry.getRank()); + } + + @Test + public void givenGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK() { + Product product = new Product("milk", 2.5); + product.setSales(30); + GenericEntry entry = new GenericEntry(product); + + assertEquals(product, entry.getData()); + assertEquals(30, entry.getRank()); + } + + @Test + public void givenGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK() { + Product product = new Product("milk", 2.5); + product.setSales(30); + Optional optional = Optional.of(product); + GenericEntry entry = new GenericEntry(optional); + + assertEquals(product, entry.getData()); + assertEquals(30, entry.getRank()); + } + + @Test + public void givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK() { + MapEntry entry = new MapEntry("sample", 1); + + assertEquals("sample", entry.getKey()); + assertEquals(1, entry.getValue() + .intValue()); + } +} diff --git a/core-java-modules/core-java-lang-oop/.gitignore b/core-java-modules/core-java-lang-oop/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/core-java-modules/core-java-lang-oop/.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-modules/core-java-lang-oop/README.md b/core-java-modules/core-java-lang-oop/README.md new file mode 100644 index 0000000000..c9ee9a9e94 --- /dev/null +++ b/core-java-modules/core-java-lang-oop/README.md @@ -0,0 +1,24 @@ +========= + +## Core Java Lang OOP Cookbooks and Examples + +### 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) +- [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) +- [Guide to Inheritance in Java](http://www.baeldung.com/java-inheritance) +- [Object Type Casting in Java](http://www.baeldung.com/java-type-casting) +- [The “final” Keyword in Java](http://www.baeldung.com/java-final) +- [Type Erasure in Java Explained](http://www.baeldung.com/java-type-erasure) +- [Pass-By-Value as a Parameter Passing Mechanism in Java](http://www.baeldung.com/java-pass-by-value-or-pass-by-reference) +- [Variable and Method Hiding in Java](http://www.baeldung.com/java-variable-method-hiding) +- [Access Modifiers in Java](http://www.baeldung.com/java-access-modifiers) +- [Guide to the super Java Keyword](http://www.baeldung.com/java-super) +- [Guide to the this Java Keyword](http://www.baeldung.com/java-this) +- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object) +- [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) diff --git a/core-java-modules/core-java-lang-oop/pom.xml b/core-java-modules/core-java-lang-oop/pom.xml new file mode 100644 index 0000000000..c9bb3b3e5a --- /dev/null +++ b/core-java-modules/core-java-lang-oop/pom.xml @@ -0,0 +1,90 @@ + + 4.0.0 + com.baeldung + core-java-lang-oop + 0.1.0-SNAPSHOT + core-java-lang-oop + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.google.code.gson + gson + ${gson.version} + + + + log4j + log4j + ${log4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + nl.jqno.equalsverifier + equalsverifier + ${equalsverifier.version} + test + + + + + core-java-lang-oop + + + src/main/resources + true + + + + + + + + 2.8.5 + 2.8.2 + + + 3.5 + + 3.10.0 + 3.0.3 + + + diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/Public.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/Public.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/Public.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/Public.java diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/SubClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/SubClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/SubClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/SubClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/SuperPublic.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/SuperPublic.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/SuperPublic.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/SuperPublic.java diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherPublic.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherPublic.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherPublic.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherPublic.java diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherSubClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherSubClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherSubClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherSubClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherSuperPublic.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherSuperPublic.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/accessmodifiers/another/AnotherSuperPublic.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/accessmodifiers/another/AnotherSuperPublic.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/Animal.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Animal.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/Animal.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Animal.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/AnimalFeeder.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/AnimalFeeder.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/AnimalFeeder.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/AnimalFeeder.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/AnimalFeederGeneric.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/AnimalFeederGeneric.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/AnimalFeederGeneric.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/AnimalFeederGeneric.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/Cat.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Cat.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/Cat.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Cat.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/Dog.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Dog.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/Dog.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Dog.java diff --git a/core-java-lang/src/main/java/com/baeldung/casting/Mew.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Mew.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/casting/Mew.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/casting/Mew.java diff --git a/core-java-lang/src/main/java/com/baeldung/constructors/BankAccount.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/constructors/BankAccount.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/constructors/BankAccount.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/constructors/BankAccount.java diff --git a/core-java-lang/src/main/java/com/baeldung/constructors/Transaction.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/constructors/Transaction.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/constructors/Transaction.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/constructors/Transaction.java diff --git a/core-java-lang/src/main/java/com/baeldung/deepcopy/Address.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/deepcopy/Address.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/deepcopy/Address.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/deepcopy/Address.java diff --git a/core-java-lang/src/main/java/com/baeldung/deepcopy/User.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/deepcopy/User.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/deepcopy/User.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/deepcopy/User.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/Money.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Money.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/Money.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Money.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/Team.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Team.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/Team.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Team.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/Voucher.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Voucher.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/Voucher.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/Voucher.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/WrongTeam.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/WrongTeam.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/WrongTeam.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/WrongTeam.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/WrongVoucher.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/WrongVoucher.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/WrongVoucher.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/WrongVoucher.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/ComplexClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/ComplexClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/ComplexClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/ComplexClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/PrimitiveClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/PrimitiveClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/PrimitiveClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/PrimitiveClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Rectangle.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Rectangle.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Rectangle.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Rectangle.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Shape.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Shape.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Shape.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Shape.java diff --git a/core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Square.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Square.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/equalshashcode/entities/Square.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/equalshashcode/entities/Square.java diff --git a/core-java-lang/src/main/java/com/baeldung/finalkeyword/BlackCat.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/BlackCat.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalkeyword/BlackCat.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/BlackCat.java diff --git a/core-java-lang/src/main/java/com/baeldung/finalkeyword/BlackDog.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/BlackDog.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalkeyword/BlackDog.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/BlackDog.java diff --git a/core-java-lang/src/main/java/com/baeldung/finalkeyword/Cat.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/Cat.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalkeyword/Cat.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/Cat.java diff --git a/core-java-lang/src/main/java/com/baeldung/finalkeyword/Dog.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/Dog.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalkeyword/Dog.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/finalkeyword/Dog.java diff --git a/core-java-lang/src/main/java/com/baeldung/hashcode/entities/User.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/hashcode/entities/User.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/hashcode/entities/User.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/hashcode/entities/User.java diff --git a/core-java-lang/src/main/java/com/baeldung/immutableobjects/Currency.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/immutableobjects/Currency.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/immutableobjects/Currency.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/immutableobjects/Currency.java diff --git a/core-java-lang/src/main/java/com/baeldung/immutableobjects/Money.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/immutableobjects/Money.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/immutableobjects/Money.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/immutableobjects/Money.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/ArmoredCar.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/ArmoredCar.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/inheritance/ArmoredCar.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/ArmoredCar.java index b6bb5181b8..ad654ba31a 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/ArmoredCar.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/ArmoredCar.java @@ -1,43 +1,43 @@ -package com.baeldung.inheritance; - -public class ArmoredCar extends Car implements Floatable, Flyable{ - private int bulletProofWindows; - private String model; - - public void remoteStartCar() { - // this vehicle can be started by using a remote control - } - - public String registerModel() { - return model; - } - - public String getAValue() { - return super.model; // returns value of model defined in base class Car - // return this.model; // will return value of model defined in ArmoredCar - // return model; // will return value of model defined in ArmoredCar - } - - public static String msg() { - // return super.msg(); // this won't compile. - return "ArmoredCar"; - } - - @Override - public void floatOnWater() { - System.out.println("I can float!"); - } - - @Override - public void fly() { - System.out.println("I can fly!"); - } - - public void aMethod() { - // System.out.println(duration); // Won't compile - System.out.println(Floatable.duration); // outputs 10 - System.out.println(Flyable.duration); // outputs 20 - } - - -} +package com.baeldung.inheritance; + +public class ArmoredCar extends Car implements Floatable, Flyable{ + private int bulletProofWindows; + private String model; + + public void remoteStartCar() { + // this vehicle can be started by using a remote control + } + + public String registerModel() { + return model; + } + + public String getAValue() { + return super.model; // returns value of model defined in base class Car + // return this.model; // will return value of model defined in ArmoredCar + // return model; // will return value of model defined in ArmoredCar + } + + public static String msg() { + // return super.msg(); // this won't compile. + return "ArmoredCar"; + } + + @Override + public void floatOnWater() { + System.out.println("I can float!"); + } + + @Override + public void fly() { + System.out.println("I can fly!"); + } + + public void aMethod() { + // System.out.println(duration); // Won't compile + System.out.println(Floatable.duration); // outputs 10 + System.out.println(Flyable.duration); // outputs 20 + } + + +} diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/BMW.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/BMW.java similarity index 93% rename from core-java-lang/src/main/java/com/baeldung/inheritance/BMW.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/BMW.java index 8ad3bb683f..8eb6198203 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/BMW.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/BMW.java @@ -1,12 +1,12 @@ -package com.baeldung.inheritance; - -public class BMW extends Car { - public BMW() { - super(5, "BMW"); - } - - @Override - public String toString() { - return model; - } -} +package com.baeldung.inheritance; + +public class BMW extends Car { + public BMW() { + super(5, "BMW"); + } + + @Override + public String toString() { + return model; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/Car.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Car.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/inheritance/Car.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Car.java index 21ea9ea569..ddb06dcf08 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/Car.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Car.java @@ -1,32 +1,32 @@ -package com.baeldung.inheritance; - -public class Car { - private final int DEFAULT_WHEEL_COUNT = 5; - private final String DEFAULT_MODEL = "Basic"; - - protected int wheels; - protected String model; - - public Car() { - this.wheels = DEFAULT_WHEEL_COUNT; - this.model = DEFAULT_MODEL; - } - - public Car(int wheels, String model) { - this.wheels = wheels; - this.model = model; - } - - public void start() { - // Check essential parts - // If okay, start. - } - public static int count = 10; - public static String msg() { - return "Car"; - } - - public String toString() { - return model; - } +package com.baeldung.inheritance; + +public class Car { + private final int DEFAULT_WHEEL_COUNT = 5; + private final String DEFAULT_MODEL = "Basic"; + + protected int wheels; + protected String model; + + public Car() { + this.wheels = DEFAULT_WHEEL_COUNT; + this.model = DEFAULT_MODEL; + } + + public Car(int wheels, String model) { + this.wheels = wheels; + this.model = model; + } + + public void start() { + // Check essential parts + // If okay, start. + } + public static int count = 10; + public static String msg() { + return "Car"; + } + + public String toString() { + return model; + } } \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/Employee.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Employee.java similarity index 94% rename from core-java-lang/src/main/java/com/baeldung/inheritance/Employee.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Employee.java index 599a1d7331..9018382087 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/Employee.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Employee.java @@ -1,15 +1,15 @@ -package com.baeldung.inheritance; - -public class Employee { - private String name; - private Car car; - - public Employee(String name, Car car) { - this.name = name; - this.car = car; - } - - public Car getCar() { - return car; - } +package com.baeldung.inheritance; + +public class Employee { + private String name; + private Car car; + + public Employee(String name, Car car) { + this.name = name; + this.car = car; + } + + public Car getCar() { + return car; + } } \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/Floatable.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Floatable.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/inheritance/Floatable.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Floatable.java index c0b456dffb..b90163487a 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/Floatable.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Floatable.java @@ -1,10 +1,10 @@ -package com.baeldung.inheritance; - -public interface Floatable { - int duration = 10; - void floatOnWater(); - - default void repair() { - System.out.println("Repairing Floatable object"); - } -} +package com.baeldung.inheritance; + +public interface Floatable { + int duration = 10; + void floatOnWater(); + + default void repair() { + System.out.println("Repairing Floatable object"); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/Flyable.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Flyable.java similarity index 94% rename from core-java-lang/src/main/java/com/baeldung/inheritance/Flyable.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Flyable.java index cb8244cf5b..a25ce6f91b 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/Flyable.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/Flyable.java @@ -1,13 +1,13 @@ -package com.baeldung.inheritance; - -public interface Flyable { - int duration = 10; - void fly(); - - /* - * Commented - */ - //default void repair() { - // System.out.println("Repairing Flyable object"); - //} -} +package com.baeldung.inheritance; + +public interface Flyable { + int duration = 10; + void fly(); + + /* + * Commented + */ + //default void repair() { + // System.out.println("Repairing Flyable object"); + //} +} diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/SpaceCar.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceCar.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/inheritance/SpaceCar.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceCar.java index 8c23b26da9..76a44411db 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/SpaceCar.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceCar.java @@ -1,18 +1,18 @@ -package com.baeldung.inheritance; - -public class SpaceCar extends Car implements SpaceTraveller { - @Override - public void floatOnWater() { - System.out.println("SpaceCar floating!"); - } - - @Override - public void fly() { - System.out.println("SpaceCar flying!"); - } - - @Override - public void remoteControl() { - System.out.println("SpaceCar being controlled remotely!"); - } -} +package com.baeldung.inheritance; + +public class SpaceCar extends Car implements SpaceTraveller { + @Override + public void floatOnWater() { + System.out.println("SpaceCar floating!"); + } + + @Override + public void fly() { + System.out.println("SpaceCar flying!"); + } + + @Override + public void remoteControl() { + System.out.println("SpaceCar being controlled remotely!"); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/inheritance/SpaceTraveller.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceTraveller.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/inheritance/SpaceTraveller.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceTraveller.java index 9b66441791..3a473af093 100644 --- a/core-java-lang/src/main/java/com/baeldung/inheritance/SpaceTraveller.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritance/SpaceTraveller.java @@ -1,6 +1,6 @@ -package com.baeldung.inheritance; - -public interface SpaceTraveller extends Floatable, Flyable { - int duration = 10; - void remoteControl(); +package com.baeldung.inheritance; + +public interface SpaceTraveller extends Floatable, Flyable { + int duration = 10; + void remoteControl(); } \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/application/Application.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/application/Application.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/application/Application.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/application/Application.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Actress.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Actress.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Actress.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Actress.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Computer.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Computer.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Computer.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Computer.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Memory.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Memory.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Memory.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Memory.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Person.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Person.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Person.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Person.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Processor.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Processor.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Processor.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Processor.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/SoundCard.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/SoundCard.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/SoundCard.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/SoundCard.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardMemory.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardMemory.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardMemory.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardMemory.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardProcessor.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardProcessor.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardProcessor.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardProcessor.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardSoundCard.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardSoundCard.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/StandardSoundCard.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/StandardSoundCard.java diff --git a/core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Waitress.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Waitress.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/inheritancecomposition/model/Waitress.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/inheritancecomposition/model/Waitress.java diff --git a/core-java-lang/src/main/java/com/baeldung/initializationguide/User.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/initializationguide/User.java similarity index 94% rename from core-java-lang/src/main/java/com/baeldung/initializationguide/User.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/initializationguide/User.java index e2e3f051dd..1d9a872d69 100644 --- a/core-java-lang/src/main/java/com/baeldung/initializationguide/User.java +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/initializationguide/User.java @@ -1,53 +1,53 @@ -package com.baeldung.initializationguide; - -import java.io.Serializable; - -public class User implements Serializable, Cloneable { - private static final long serialVersionUID = 1L; - static String forum; - private String name; - private int id; - - { - id = 0; - System.out.println("Instance Initializer"); - } - - static { - forum = "Java"; - System.out.println("Static Initializer"); - } - - public User(String name, int id) { - super(); - this.name = name; - this.id = id; - } - - public User() { - System.out.println("Constructor"); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return this; - } - -} - +package com.baeldung.initializationguide; + +import java.io.Serializable; + +public class User implements Serializable, Cloneable { + private static final long serialVersionUID = 1L; + static String forum; + private String name; + private int id; + + { + id = 0; + System.out.println("Instance Initializer"); + } + + static { + forum = "Java"; + System.out.println("Static Initializer"); + } + + public User(String name, int id) { + super(); + this.name = name; + this.id = id; + } + + public User() { + System.out.println("Constructor"); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return this; + } + +} + diff --git a/core-java-lang/src/main/java/com/baeldung/keyword/KeywordDemo.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/KeywordDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keyword/KeywordDemo.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/KeywordDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/keyword/superkeyword/SuperBase.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/superkeyword/SuperBase.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keyword/superkeyword/SuperBase.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/superkeyword/SuperBase.java diff --git a/core-java-lang/src/main/java/com/baeldung/keyword/superkeyword/SuperSub.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/superkeyword/SuperSub.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keyword/superkeyword/SuperSub.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/superkeyword/SuperSub.java diff --git a/core-java-lang/src/main/java/com/baeldung/keyword/thiskeyword/KeywordUnitTest.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/thiskeyword/KeywordUnitTest.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keyword/thiskeyword/KeywordUnitTest.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/keyword/thiskeyword/KeywordUnitTest.java diff --git a/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/DeletableShape.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/DeletableShape.java new file mode 100644 index 0000000000..800ba6f46c --- /dev/null +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/DeletableShape.java @@ -0,0 +1,5 @@ +package com.baeldung.markerinterface; + +public interface DeletableShape extends Shape { + +} diff --git a/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Rectangle.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Rectangle.java new file mode 100644 index 0000000000..659f2af2ee --- /dev/null +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Rectangle.java @@ -0,0 +1,22 @@ +package com.baeldung.markerinterface; + +public class Rectangle implements DeletableShape { + + private double width; + private double height; + + public Rectangle(double width, double height) { + this.width = width; + this.height = height; + } + + @Override + public double getArea() { + return width * height; + } + + @Override + public double getCircumference() { + return 2 * (width + height); + } +} diff --git a/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Shape.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Shape.java new file mode 100644 index 0000000000..b1db906087 --- /dev/null +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/Shape.java @@ -0,0 +1,6 @@ +package com.baeldung.markerinterface; + +public interface Shape { + double getArea(); + double getCircumference(); +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/ShapeDao.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/ShapeDao.java new file mode 100644 index 0000000000..1b95c7b307 --- /dev/null +++ b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/markerinterface/ShapeDao.java @@ -0,0 +1,14 @@ +package com.baeldung.markerinterface; + +public class ShapeDao { + + public boolean delete(Object object) { + if (!(object instanceof DeletableShape)) { + return false; + } + // Calling the code that deletes the entity from the database + + return true; + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/application/Application.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/application/Application.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/application/Application.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/application/Application.java diff --git a/core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/model/Car.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/model/Car.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/model/Car.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/model/Car.java diff --git a/core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/model/Vehicle.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/model/Vehicle.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/model/Vehicle.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/model/Vehicle.java diff --git a/core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/util/Multiplier.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/util/Multiplier.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/methodoverloadingoverriding/util/Multiplier.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/methodoverloadingoverriding/util/Multiplier.java diff --git a/core-java-lang/src/main/java/com/baeldung/polymorphism/FileManager.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/FileManager.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/polymorphism/FileManager.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/FileManager.java diff --git a/core-java-lang/src/main/java/com/baeldung/polymorphism/GenericFile.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/GenericFile.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/polymorphism/GenericFile.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/GenericFile.java diff --git a/core-java-lang/src/main/java/com/baeldung/polymorphism/ImageFile.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/ImageFile.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/polymorphism/ImageFile.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/ImageFile.java diff --git a/core-java-lang/src/main/java/com/baeldung/polymorphism/TextFile.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/TextFile.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/polymorphism/TextFile.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/polymorphism/TextFile.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/method/BaseMethodClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/BaseMethodClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/method/BaseMethodClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/BaseMethodClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/method/ChildMethodClass.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/ChildMethodClass.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/method/ChildMethodClass.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/ChildMethodClass.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/method/MethodHidingDemo.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/MethodHidingDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/method/MethodHidingDemo.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/method/MethodHidingDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/variable/ChildVariable.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/ChildVariable.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/variable/ChildVariable.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/ChildVariable.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/variable/HideVariable.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/HideVariable.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/variable/HideVariable.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/HideVariable.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/variable/ParentVariable.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/ParentVariable.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/variable/ParentVariable.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/ParentVariable.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/variable/VariableHidingDemo.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/VariableHidingDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/scope/variable/VariableHidingDemo.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/scope/variable/VariableHidingDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/staticdemo/Car.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/Car.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/staticdemo/Car.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/Car.java diff --git a/core-java-lang/src/main/java/com/baeldung/staticdemo/Singleton.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/Singleton.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/staticdemo/Singleton.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/Singleton.java diff --git a/core-java-lang/src/main/java/com/baeldung/staticdemo/StaticBlock.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/StaticBlock.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/staticdemo/StaticBlock.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/staticdemo/StaticBlock.java diff --git a/core-java-lang/src/main/java/com/baeldung/typeerasure/ArrayContentPrintUtil.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/ArrayContentPrintUtil.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/typeerasure/ArrayContentPrintUtil.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/ArrayContentPrintUtil.java diff --git a/core-java-lang/src/main/java/com/baeldung/typeerasure/BoundStack.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/BoundStack.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/typeerasure/BoundStack.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/BoundStack.java diff --git a/core-java-lang/src/main/java/com/baeldung/typeerasure/IntegerStack.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/IntegerStack.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/typeerasure/IntegerStack.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/IntegerStack.java diff --git a/core-java-lang/src/main/java/com/baeldung/typeerasure/Stack.java b/core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/Stack.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/typeerasure/Stack.java rename to core-java-modules/core-java-lang-oop/src/main/java/com/baeldung/typeerasure/Stack.java diff --git a/core-java/src/main/resources/logback.xml b/core-java-modules/core-java-lang-oop/src/main/resources/logback.xml similarity index 100% rename from core-java/src/main/resources/logback.xml rename to core-java-modules/core-java-lang-oop/src/main/resources/logback.xml diff --git a/core-java-lang/src/test/java/com/baeldung/casting/CastingUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/casting/CastingUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/casting/CastingUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/casting/CastingUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/deepcopy/DeepCopyUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/deepcopy/DeepCopyUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/deepcopy/DeepCopyUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/deepcopy/DeepCopyUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/deepcopy/ShallowCopyUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/deepcopy/ShallowCopyUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/deepcopy/ShallowCopyUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/deepcopy/ShallowCopyUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/equalshashcode/MoneyUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/MoneyUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/equalshashcode/MoneyUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/MoneyUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/equalshashcode/TeamUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/TeamUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/equalshashcode/TeamUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/TeamUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/ComplexClassUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/ComplexClassUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/ComplexClassUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/ComplexClassUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/PrimitiveClassUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/PrimitiveClassUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/PrimitiveClassUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/PrimitiveClassUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/SquareClassUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/SquareClassUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/equalshashcode/entities/SquareClassUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/equalshashcode/entities/SquareClassUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/finalkeyword/FinalUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/finalkeyword/FinalUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/finalkeyword/FinalUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/finalkeyword/FinalUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/hashcode/application/ApplicationUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/hashcode/application/ApplicationUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/hashcode/application/ApplicationUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/hashcode/application/ApplicationUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/hashcode/entities/UserUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/hashcode/entities/UserUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/hashcode/entities/UserUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/hashcode/entities/UserUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/inheritance/AppUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritance/AppUnitTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/inheritance/AppUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritance/AppUnitTest.java index 1c3c2fff35..0d9dfed27a 100644 --- a/core-java-lang/src/test/java/com/baeldung/inheritance/AppUnitTest.java +++ b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritance/AppUnitTest.java @@ -1,46 +1,46 @@ -package com.baeldung.inheritance; - -import com.baeldung.inheritance.*; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -public class AppUnitTest extends TestCase { - - public AppUnitTest(String testName) { - super( testName ); - } - - public static Test suite() { - return new TestSuite(AppUnitTest.class); - } - - @SuppressWarnings("static-access") - public void testStaticMethodUsingBaseClassVariable() { - Car first = new ArmoredCar(); - assertEquals("Car", first.msg()); - } - - @SuppressWarnings("static-access") - public void testStaticMethodUsingDerivedClassVariable() { - ArmoredCar second = new ArmoredCar(); - assertEquals("ArmoredCar", second.msg()); - } - - public void testAssignArmoredCarToCar() { - Employee e1 = new Employee("Shreya", new ArmoredCar()); - assertNotNull(e1.getCar()); - } - - public void testAssignSpaceCarToCar() { - Employee e2 = new Employee("Paul", new SpaceCar()); - assertNotNull(e2.getCar()); - } - - public void testBMWToCar() { - Employee e3 = new Employee("Pavni", new BMW()); - assertNotNull(e3.getCar()); - } - -} +package com.baeldung.inheritance; + +import com.baeldung.inheritance.*; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class AppUnitTest extends TestCase { + + public AppUnitTest(String testName) { + super( testName ); + } + + public static Test suite() { + return new TestSuite(AppUnitTest.class); + } + + @SuppressWarnings("static-access") + public void testStaticMethodUsingBaseClassVariable() { + Car first = new ArmoredCar(); + assertEquals("Car", first.msg()); + } + + @SuppressWarnings("static-access") + public void testStaticMethodUsingDerivedClassVariable() { + ArmoredCar second = new ArmoredCar(); + assertEquals("ArmoredCar", second.msg()); + } + + public void testAssignArmoredCarToCar() { + Employee e1 = new Employee("Shreya", new ArmoredCar()); + assertNotNull(e1.getCar()); + } + + public void testAssignSpaceCarToCar() { + Employee e2 = new Employee("Paul", new SpaceCar()); + assertNotNull(e2.getCar()); + } + + public void testBMWToCar() { + Employee e3 = new Employee("Pavni", new BMW()); + assertNotNull(e3.getCar()); + } + +} diff --git a/core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/ActressUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/ActressUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/ActressUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/ActressUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/CompositionUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/CompositionUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/CompositionUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/CompositionUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/InheritanceUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/InheritanceUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/InheritanceUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/InheritanceUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/PersonUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/PersonUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/PersonUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/PersonUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/WaitressUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/WaitressUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/inheritancecomposition/test/WaitressUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/inheritancecomposition/test/WaitressUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/initializationguide/UserUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/initializationguide/UserUnitTest.java similarity index 97% rename from core-java-lang/src/test/java/com/baeldung/initializationguide/UserUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/initializationguide/UserUnitTest.java index f74384e6f7..a26b602609 100644 --- a/core-java-lang/src/test/java/com/baeldung/initializationguide/UserUnitTest.java +++ b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/initializationguide/UserUnitTest.java @@ -1,37 +1,37 @@ -package com.baeldung.initializationguide; -import org.junit.Before; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.*; - -import java.lang.reflect.InvocationTargetException; - -public class UserUnitTest { - - @Test - public void givenUserInstance_whenIntializedWithNew_thenInstanceIsNotNull() { - User user = new User("Alice", 1); - assertThat(user).isNotNull(); - } - - @Test - public void givenUserInstance_whenInitializedWithReflection_thenInstanceIsNotNull() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { - User user = User.class.getConstructor(String.class, int.class) - .newInstance("Alice", 2); - assertThat(user).isNotNull(); - } - - @Test - public void givenUserInstance_whenCopiedWithClone_thenExactMatchIsCreated() throws CloneNotSupportedException { - User user = new User("Alice", 3); - User clonedUser = (User) user.clone(); - assertThat(clonedUser).isEqualTo(user); - } - - @Test - public void givenUserInstance_whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() { - User user = new User(); - assertThat(user.getName()).isNull(); - assertThat(user.getId() == 0); - } -} +package com.baeldung.initializationguide; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.*; + +import java.lang.reflect.InvocationTargetException; + +public class UserUnitTest { + + @Test + public void givenUserInstance_whenIntializedWithNew_thenInstanceIsNotNull() { + User user = new User("Alice", 1); + assertThat(user).isNotNull(); + } + + @Test + public void givenUserInstance_whenInitializedWithReflection_thenInstanceIsNotNull() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + User user = User.class.getConstructor(String.class, int.class) + .newInstance("Alice", 2); + assertThat(user).isNotNull(); + } + + @Test + public void givenUserInstance_whenCopiedWithClone_thenExactMatchIsCreated() throws CloneNotSupportedException { + User user = new User("Alice", 3); + User clonedUser = (User) user.clone(); + assertThat(clonedUser).isEqualTo(user); + } + + @Test + public void givenUserInstance_whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() { + User user = new User(); + assertThat(user.getName()).isNull(); + assertThat(user.getId() == 0); + } +} diff --git a/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/markerinterface/MarkerInterfaceUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/markerinterface/MarkerInterfaceUnitTest.java new file mode 100644 index 0000000000..81cd51ce51 --- /dev/null +++ b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/markerinterface/MarkerInterfaceUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.markerinterface; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class MarkerInterfaceUnitTest { + + @Test + public void givenDeletableObjectThenTrueReturned() { + ShapeDao shapeDao = new ShapeDao(); + Object rectangle = new Rectangle(2, 3); + + boolean result = shapeDao.delete(rectangle); + assertEquals(true, result); + } + + @Test + public void givenNonDeletableObjectThenFalseReturned() { + ShapeDao shapeDao = new ShapeDao(); + Object object = new Object(); + + boolean result = shapeDao.delete(object); + assertEquals(false, result); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverloadingUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverloadingUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverloadingUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverloadingUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverridingUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverridingUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverridingUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/methodoverloadingoverriding/test/MethodOverridingUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/parameterpassing/NonPrimitivesUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/parameterpassing/NonPrimitivesUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/parameterpassing/NonPrimitivesUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/parameterpassing/NonPrimitivesUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/parameterpassing/PrimitivesUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/parameterpassing/PrimitivesUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/parameterpassing/PrimitivesUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/parameterpassing/PrimitivesUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/polymorphism/PolymorphismUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/polymorphism/PolymorphismUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/polymorphism/PolymorphismUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/polymorphism/PolymorphismUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/staticdemo/CarIntegrationTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/CarIntegrationTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/staticdemo/CarIntegrationTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/CarIntegrationTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/staticdemo/SingletonIntegrationTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/SingletonIntegrationTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/staticdemo/SingletonIntegrationTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/SingletonIntegrationTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/staticdemo/StaticBlockIntegrationTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/StaticBlockIntegrationTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/staticdemo/StaticBlockIntegrationTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/staticdemo/StaticBlockIntegrationTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/typeerasure/TypeErasureUnitTest.java b/core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/typeerasure/TypeErasureUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/typeerasure/TypeErasureUnitTest.java rename to core-java-modules/core-java-lang-oop/src/test/java/com/baeldung/typeerasure/TypeErasureUnitTest.java diff --git a/core-java-sun/src/main/java/com/baeldung/.gitignore b/core-java-modules/core-java-lang-oop/src/test/resources/.gitignore similarity index 100% rename from core-java-sun/src/main/java/com/baeldung/.gitignore rename to core-java-modules/core-java-lang-oop/src/test/resources/.gitignore diff --git a/core-java-networking/.gitignore b/core-java-modules/core-java-lang-syntax/.gitignore similarity index 100% rename from core-java-networking/.gitignore rename to core-java-modules/core-java-lang-syntax/.gitignore diff --git a/core-java-modules/core-java-lang-syntax/README.md b/core-java-modules/core-java-lang-syntax/README.md new file mode 100644 index 0000000000..81c3d6c354 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/README.md @@ -0,0 +1,20 @@ +========= + +## Core Java Lang Syntax Cookbooks and Examples + +### Relevant Articles: +- [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) +- [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break) +- [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) +- [Infinite Loops in Java](http://www.baeldung.com/infinite-loops-java) +- [Quick Guide to java.lang.System](http://www.baeldung.com/java-lang-system) +- [Java Switch Statement](https://www.baeldung.com/java-switch) +- [The Modulo Operator in Java](https://www.baeldung.com/modulo-java) +- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator) +- [Java instanceof Operator](https://www.baeldung.com/java-instanceof) diff --git a/core-java-modules/core-java-lang-syntax/pom.xml b/core-java-modules/core-java-lang-syntax/pom.xml new file mode 100644 index 0000000000..46fa8d1206 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + com.baeldung + core-java-lang-syntax + 0.1.0-SNAPSHOT + core-java-lang-syntax + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + + log4j + log4j + ${log4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + core-java-lang-syntax + + + src/main/resources + true + + + + + + + 3.10.0 + + + diff --git a/core-java-lang/src/main/java/com/baeldung/breakcontinue/BreakContinue.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/breakcontinue/BreakContinue.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/breakcontinue/BreakContinue.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/breakcontinue/BreakContinue.java diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/breakloop/LoopBreaking.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/breakloop/LoopBreaking.java new file mode 100644 index 0000000000..90b99f57cb --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/breakloop/LoopBreaking.java @@ -0,0 +1,47 @@ +package com.baeldung.breakloop; + +public class LoopBreaking { + + public String simpleBreak() { + String result = ""; + for (int outerCounter = 0; outerCounter < 2; outerCounter++) { + result += "outer" + outerCounter; + for (int innerCounter = 0; innerCounter < 2; innerCounter++) { + result += "inner" + innerCounter; + if (innerCounter == 0) { + break; + } + } + } + return result; + } + + public String labelBreak() { + String result = ""; + myBreakLabel: + for (int outerCounter = 0; outerCounter < 2; outerCounter++) { + result += "outer" + outerCounter; + for (int innerCounter = 0; innerCounter < 2; innerCounter++) { + result += "inner" + innerCounter; + if (innerCounter == 0) { + break myBreakLabel; + } + } + } + return result; + } + + public String usingReturn() { + String result = ""; + for (int outerCounter = 0; outerCounter < 2; outerCounter++) { + result += "outer" + outerCounter; + for (int innerCounter = 0; innerCounter < 2; innerCounter++) { + result += "inner" + innerCounter; + if (innerCounter == 0) { + return result; + } + } + } + return "failed"; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/enums/Pizza.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/enums/Pizza.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java diff --git a/core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java diff --git a/core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java diff --git a/core-java-lang/src/main/java/com/baeldung/generics/Building.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/generics/Building.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java diff --git a/core-java-lang/src/main/java/com/baeldung/generics/Generics.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java similarity index 85% rename from core-java-lang/src/main/java/com/baeldung/generics/Generics.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java index e0536ca02e..1c4082c58b 100644 --- a/core-java-lang/src/main/java/com/baeldung/generics/Generics.java +++ b/core-java-modules/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/src/main/java/com/baeldung/generics/House.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/generics/House.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java new file mode 100644 index 0000000000..1d9a872d69 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java @@ -0,0 +1,53 @@ +package com.baeldung.initializationguide; + +import java.io.Serializable; + +public class User implements Serializable, Cloneable { + private static final long serialVersionUID = 1L; + static String forum; + private String name; + private int id; + + { + id = 0; + System.out.println("Instance Initializer"); + } + + static { + forum = "Java"; + System.out.println("Static Initializer"); + } + + public User(String name, int id) { + super(); + this.name = name; + this.id = id; + } + + public User() { + System.out.println("Constructor"); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return this; + } + +} + diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java new file mode 100644 index 0000000000..807020d267 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java @@ -0,0 +1,5 @@ +package com.baeldung.keyword; + +public class Circle extends Round implements Shape { + +} diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java new file mode 100644 index 0000000000..64274cbb6b --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Ring extends Round { +} diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java new file mode 100644 index 0000000000..37008de09c --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Round { +} diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java new file mode 100644 index 0000000000..437917c29e --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public interface Shape { +} diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java new file mode 100644 index 0000000000..4cb6ed72ba --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Triangle implements Shape { +} diff --git a/core-java-lang/src/main/java/com/baeldung/loops/InfiniteLoops.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/InfiniteLoops.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/loops/InfiniteLoops.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/InfiniteLoops.java index 0706c85db8..4952fd7b35 100644 --- a/core-java-lang/src/main/java/com/baeldung/loops/InfiniteLoops.java +++ b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/InfiniteLoops.java @@ -1,23 +1,23 @@ -package com.baeldung.loops; - -public class InfiniteLoops { - - public void infiniteLoopUsingWhile() { - while (true) { - System.out.println("Infinite loop using while"); - } - } - - public void infiniteLoopUsingFor() { - for (;;) { - System.out.println("Infinite loop using for"); - } - } - - public void infiniteLoopUsingDoWhile() { - do { - System.out.println("Infinite loop using do-while"); - } while (true); - } - -} +package com.baeldung.loops; + +public class InfiniteLoops { + + public void infiniteLoopUsingWhile() { + while (true) { + System.out.println("Infinite loop using while"); + } + } + + public void infiniteLoopUsingFor() { + for (;;) { + System.out.println("Infinite loop using for"); + } + } + + public void infiniteLoopUsingDoWhile() { + do { + System.out.println("Infinite loop using do-while"); + } while (true); + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/loops/LoopsInJava.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/loops/LoopsInJava.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java diff --git a/core-java-lang/src/main/java/com/baeldung/switchstatement/SwitchStatement.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/switchstatement/SwitchStatement.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/ChatWindow.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/ChatWindow.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/ChatWindow.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/ChatWindow.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/DateTimeService.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/DateTimeService.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/DateTimeService.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/DateTimeService.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/EnvironmentVariables.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/EnvironmentVariables.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/EnvironmentVariables.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/EnvironmentVariables.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemErrDemo.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemErrDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/SystemErrDemo.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemErrDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemExitDemo.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemExitDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/SystemExitDemo.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemExitDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemOutDemo.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemOutDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/SystemOutDemo.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemOutDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/system/UserCredentials.java b/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/UserCredentials.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/system/UserCredentials.java rename to core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/system/UserCredentials.java diff --git a/core-java-lang/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/breakloop/LoopBreakingUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/breakloop/LoopBreakingUnitTest.java new file mode 100644 index 0000000000..c4b6573c86 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/breakloop/LoopBreakingUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.breakloop; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LoopBreakingUnitTest { + + private LoopBreaking loopBreaking = new LoopBreaking(); + + @Test + void whenUsingBreak_shouldBreakInnerLoop() { + assertEquals("outer0inner0outer1inner0", loopBreaking.simpleBreak()); + } + + @Test + void whenUsingLabeledBreak_shouldBreakInnerLoopAndOuterLoop() { + assertEquals("outer0inner0", loopBreaking.labelBreak()); + } + + @Test + void whenUsingReturn_shouldBreakInnerLoopAndOuterLoop() { + assertEquals("outer0inner0", loopBreaking.usingReturn()); + } +} \ No newline at end of file diff --git a/core-java-lang/src/test/java/com/baeldung/enums/PizzaUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/enums/PizzaUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/generics/GenericsUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java similarity index 87% rename from core-java-lang/src/test/java/com/baeldung/generics/GenericsUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java index aca0b182a0..0bdf0afc15 100644 --- a/core-java-lang/src/test/java/com/baeldung/generics/GenericsUnitTest.java +++ b/core-java-modules/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 diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java new file mode 100644 index 0000000000..a26b602609 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.initializationguide; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.*; + +import java.lang.reflect.InvocationTargetException; + +public class UserUnitTest { + + @Test + public void givenUserInstance_whenIntializedWithNew_thenInstanceIsNotNull() { + User user = new User("Alice", 1); + assertThat(user).isNotNull(); + } + + @Test + public void givenUserInstance_whenInitializedWithReflection_thenInstanceIsNotNull() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + User user = User.class.getConstructor(String.class, int.class) + .newInstance("Alice", 2); + assertThat(user).isNotNull(); + } + + @Test + public void givenUserInstance_whenCopiedWithClone_thenExactMatchIsCreated() throws CloneNotSupportedException { + User user = new User("Alice", 3); + User clonedUser = (User) user.clone(); + assertThat(clonedUser).isEqualTo(user); + } + + @Test + public void givenUserInstance_whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() { + User user = new User(); + assertThat(user.getName()).isNull(); + assertThat(user.getId() == 0); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Car.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Car.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Car.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Car.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Diesel.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Diesel.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Diesel.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Diesel.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Engine.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Engine.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Engine.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Engine.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Vehicle.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Vehicle.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Vehicle.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Vehicle.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java new file mode 100644 index 0000000000..6966fa3944 --- /dev/null +++ b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java @@ -0,0 +1,55 @@ +package com.baeldung.keyword.test; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import com.baeldung.keyword.Circle; +import com.baeldung.keyword.Ring; +import com.baeldung.keyword.Round; +import com.baeldung.keyword.Shape; +import com.baeldung.keyword.Triangle; + +public class InstanceOfUnitTest { + + @Test + public void giveWhenInstanceIsCorrect_thenReturnTrue() { + Ring ring = new Ring(); + Assert.assertTrue("ring is instance of Round ", ring instanceof Round); + } + + @Test + public void giveWhenObjectIsInstanceOfType_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Circle ", circle instanceof Circle); + } + + + @Test + public void giveWhenInstanceIsOfSubtype_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Round", circle instanceof Round); + } + + @Test + public void giveWhenTypeIsInterface_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Shape", circle instanceof Shape); + } + + @Test + public void giveWhenTypeIsOfObjectType_thenReturnTrue() { + Thread thread = new Thread(); + Assert.assertTrue("thread is instance of Object", thread instanceof Object); + } + + @Test + public void giveWhenInstanceValueIsNull_thenReturnFalse() { + Circle circle = null; + Assert.assertFalse("circle is instance of Round", circle instanceof Round); + } + + @Test + public void giveWhenComparingClassInDiffHierarchy_thenCompilationError() { + // Assert.assertFalse("circle is instance of Triangle", circle instanceof Triangle); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/loops/WhenUsingLoops.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/WhenUsingLoops.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/loops/WhenUsingLoops.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/loops/WhenUsingLoops.java diff --git a/core-java-lang/src/test/java/com/baeldung/modulo/ModuloUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/modulo/ModuloUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/modulo/ModuloUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/modulo/ModuloUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemNanoUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemNanoUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/system/SystemNanoUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemNanoUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/varargs/FormatterUnitTest.java b/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/FormatterUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/varargs/FormatterUnitTest.java rename to core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/varargs/FormatterUnitTest.java diff --git a/core-java/.gitignore b/core-java-modules/core-java-lang/.gitignore similarity index 100% rename from core-java/.gitignore rename to core-java-modules/core-java-lang/.gitignore diff --git a/core-java-lang/README.md b/core-java-modules/core-java-lang/README.md similarity index 54% rename from core-java-lang/README.md rename to core-java-modules/core-java-lang/README.md index 69209bb193..e9169a5820 100644 --- a/core-java-lang/README.md +++ b/core-java-modules/core-java-lang/README.md @@ -4,44 +4,24 @@ ### Relevant Articles: - [Guide to Java Reflection](http://www.baeldung.com/java-reflection) -- [Introduction to Java Generics](http://www.baeldung.com/java-generics) - [Generate equals() and hashCode() with Eclipse](http://www.baeldung.com/java-eclipse-equals-and-hashcode) - [Chained Exceptions in Java](http://www.baeldung.com/java-chained-exceptions) -- [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions) - [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection) - [Iterating Over Enum Values in Java](http://www.baeldung.com/java-enum-iteration) - [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params) - [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies) - [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization) -- [Guide to hashCode() in Java](http://www.baeldung.com/java-hashcode) - [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator) -- [A Guide to the Static Keyword in Java](http://www.baeldung.com/java-static) -- [Quick Example - Comparator vs Comparable in Java](http://www.baeldung.com/java-comparator-comparable) +- [Comparator and Comparable in Java](http://www.baeldung.com/java-comparator-comparable) - [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) - [Nested Classes in Java](http://www.baeldung.com/java-nested-classes) -- [A Guide to Java Loops](http://www.baeldung.com/java-loops) -- [Varargs in Java](http://www.baeldung.com/java-varargs) - [A Guide to Inner Interfaces in Java](http://www.baeldung.com/java-inner-interfaces) -- [Polymorphism in Java](http://www.baeldung.com/java-polymorphism) - [Recursion In Java](http://www.baeldung.com/java-recursion) - [A Guide to the finalize Method in Java](http://www.baeldung.com/java-finalize) -- [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) -- [Guide to Inheritance in Java](http://www.baeldung.com/java-inheritance) -- [Object Type Casting in Java](http://www.baeldung.com/java-type-casting) -- [The "final" Keyword in Java](http://www.baeldung.com/java-final) - [A Guide to Java Enums](http://www.baeldung.com/a-guide-to-java-enums) - [Infinite Loops in Java](http://www.baeldung.com/infinite-loops-java) - [Quick Guide to java.lang.System](http://www.baeldung.com/java-lang-system) -- [Type Erasure in Java Explained](http://www.baeldung.com/java-type-erasure) - [Using Java Assertions](http://www.baeldung.com/java-assert) -- [Pass-By-Value as a Parameter Passing Mechanism in Java](http://www.baeldung.com/java-pass-by-value-or-pass-by-reference) -- [Variable and Method Hiding in Java](http://www.baeldung.com/java-variable-method-hiding) -- [Access Modifiers in Java](http://www.baeldung.com/java-access-modifiers) -- [Guide to the super Java Keyword](http://www.baeldung.com/java-super) -- [Guide to the this Java Keyword](http://www.baeldung.com/java-this) -- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object) - [ClassNotFoundException vs NoClassDefFoundError](http://www.baeldung.com/java-classnotfoundexception-and-noclassdeffounderror) - [The StackOverflowError in Java](http://www.baeldung.com/java-stack-overflow-error) - [Create a Custom Exception in Java](http://www.baeldung.com/java-new-custom-exception) @@ -50,12 +30,15 @@ - [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding) - [Difference Between Throw and Throws in Java](https://www.baeldung.com/java-throw-throws) - [Synthetic Constructs in Java](https://www.baeldung.com/java-synthetic) -- [Java Switch Statement](https://www.baeldung.com/java-switch) -- [The Modulo Operator in Java](https://www.baeldung.com/modulo-java) -- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator) - [How to Separate Double into Integer and Decimal Parts](https://www.baeldung.com/java-separate-double-into-integer-decimal-parts) - [“Sneaky Throws” in Java](http://www.baeldung.com/java-sneaky-throws) -- [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) - [Retrieving a Class Name in Java](https://www.baeldung.com/java-class-name) -- [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts) +- [Java Compound Operators](https://www.baeldung.com/java-compound-operators) +- [Guide to Java Packages](https://www.baeldung.com/java-packages) +- [The Java Native Keyword and Methods](https://www.baeldung.com/java-native) +- [If-Else Statement in Java](https://www.baeldung.com/java-if-else) +- [Control Structures in Java](https://www.baeldung.com/java-control-structures) +- [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) diff --git a/core-java-modules/core-java-lang/pom.xml b/core-java-modules/core-java-lang/pom.xml new file mode 100644 index 0000000000..45ccc8d0f5 --- /dev/null +++ b/core-java-modules/core-java-lang/pom.xml @@ -0,0 +1,88 @@ + + 4.0.0 + com.baeldung + core-java-lang + 0.1.0-SNAPSHOT + core-java-lang + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.google.code.gson + gson + ${gson.version} + + + + log4j + log4j + ${log4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + javax.mail + mail + ${javax.mail.version} + + + + + core-java-lang + + + src/main/resources + true + + + + + + 2.8.2 + + + 3.5 + + 1.5.0-b01 + + + 3.10.0 + + + diff --git a/core-java-lang/src/main/java/com/baeldung/assertion/Assertion.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/assertion/Assertion.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/assertion/Assertion.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/assertion/Assertion.java diff --git a/core-java-lang/src/main/java/com/baeldung/binding/Animal.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/Animal.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/binding/Animal.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/Animal.java diff --git a/core-java-lang/src/main/java/com/baeldung/binding/AnimalActivity.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/AnimalActivity.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/binding/AnimalActivity.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/AnimalActivity.java diff --git a/core-java-lang/src/main/java/com/baeldung/binding/Cat.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/Cat.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/binding/Cat.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/binding/Cat.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithChain.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithChain.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithChain.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithChain.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithoutChain.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithoutChain.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithoutChain.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/LogWithoutChain.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/GirlFriendOfManagerUpsetException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/GirlFriendOfManagerUpsetException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/GirlFriendOfManagerUpsetException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/GirlFriendOfManagerUpsetException.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/ManagerUpsetException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/ManagerUpsetException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/ManagerUpsetException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/ManagerUpsetException.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/NoLeaveGrantedException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/NoLeaveGrantedException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/NoLeaveGrantedException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/NoLeaveGrantedException.java diff --git a/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/TeamLeadUpsetException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/TeamLeadUpsetException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/TeamLeadUpsetException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/chainedexception/exceptions/TeamLeadUpsetException.java diff --git a/core-java-lang/src/main/java/com/baeldung/className/RetrievingClassName.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/className/RetrievingClassName.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/className/RetrievingClassName.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/className/RetrievingClassName.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparable/Player.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparable/Player.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparable/Player.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparable/Player.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparable/PlayerSorter.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparable/PlayerSorter.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparable/PlayerSorter.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparable/PlayerSorter.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparator/Player.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/Player.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparator/Player.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/Player.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeComparator.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeComparator.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeComparator.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeComparator.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeSorter.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeSorter.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeSorter.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerAgeSorter.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingComparator.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingComparator.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingComparator.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingComparator.java diff --git a/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingSorter.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingSorter.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingSorter.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/comparator/PlayerRankingSorter.java diff --git a/core-java-lang/src/main/java/com/baeldung/controlstructures/ConditionalBranches.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/controlstructures/ConditionalBranches.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/controlstructures/ConditionalBranches.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/controlstructures/ConditionalBranches.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java new file mode 100644 index 0000000000..bc4515bfc7 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/controlstructures/Loops.java @@ -0,0 +1,157 @@ +package com.baeldung.controlstructures; + +public class Loops { + + /** + * Dummy method. Only prints a generic message. + */ + private static void methodToRepeat() { + System.out.println("Dummy method."); + } + + /** + * Shows how to iterate 50 times with 3 different method/control structures. + */ + public static void repetitionTo50Examples() { + for (int i = 1; i <= 50; i++) { + methodToRepeat(); + } + + int whileCounter = 1; + while (whileCounter <= 50) { + methodToRepeat(); + whileCounter++; + } + + int count = 1; + do { + methodToRepeat(); + count++; + } while (count < 50); + } + + /** + * Splits a sentence in words, and prints each word in a new line. + * @param sentence Sentence to print as independent words. + */ + public static void printWordByWord(String sentence) { + for (String word : sentence.split(" ")) { + System.out.println(word); + } + } + + /** + * Prints text an N amount of times. Shows usage of the {@code break} branching statement. + * @param textToPrint Text to repeatedly print. + * @param times Amount to times to print received text. + */ + public static void printTextNTimes(String textToPrint, int times) { + int counter = 1; + while (true) { + System.out.println(textToPrint); + if (counter == times) { + break; + } + } + } + + /** + * Prints text an N amount of times, up to 50. Shows usage of the {@code break} branching statement. + * @param textToPrint Text to repeatedly print. + * @param times Amount to times to print received text. If times is higher than 50, textToPrint will only be printed 50 times. + */ + public static void printTextNTimesUpTo50(String textToPrint, int times) { + int counter = 1; + while (counter < 50) { + System.out.println(textToPrint); + if (counter == times) { + break; + } + } + } + + /** + * Finds the index of {@code name} in a list + * @param name The name to look for + * @param names The list of names + * @return The index where the name was found or -1 otherwise + */ + public static int findFirstInstanceOfName(String name, String[] names) { + int index = 0; + for ( ; index < names.length; index++) { + if (names[index].equals(name)) { + break; + } + } + return index == names.length ? -1 : index; + } + + /** + * Takes several names and makes a list, skipping the specified {@code name}. + * + * @param name The name to skip + * @param names The list of names + * @return The list of names as a single string, missing the specified {@code name}. + */ + public static String makeListSkippingName(String name, String[] names) { + String list = ""; + for (int i = 0; i < names.length; i++) { + if (names[i].equals(name)) { + continue; + } + list += names[i]; + } + return list; + } + + /** + * Prints an specified amount of even numbers. Shows usage of both {@code break} and {@code continue} branching statements. + * @param amountToPrint Amount of even numbers to print. + */ + public static void printEvenNumbers(int amountToPrint) { + if (amountToPrint <= 0) { // Invalid input + return; + } + int iterator = 0; + int amountPrinted = 0; + while (true) { + if (iterator % 2 == 0) { // Is an even number + System.out.println(iterator); + amountPrinted++; + iterator++; + } else { + iterator++; + continue; // Won't print + } + if (amountPrinted == amountToPrint) { + break; + } + } + } + + /** + * Prints an specified amount of even numbers, up to 100. Shows usage of both {@code break} and {@code continue} branching statements. + * @param amountToPrint Amount of even numbers to print. + */ + public static void printEvenNumbersToAMaxOf100(int amountToPrint) { + if (amountToPrint <= 0) { // Invalid input + return; + } + int iterator = 0; + int amountPrinted = 0; + while (amountPrinted < 100) { + if (iterator % 2 == 0) { // Is an even number + System.out.println(iterator); + amountPrinted++; + iterator++; + } else { + iterator++; + continue; // Won't print + } + if (amountPrinted == amountToPrint) { + break; + } + } + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/customexception/FileManager.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/FileManager.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/customexception/FileManager.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/FileManager.java diff --git a/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileExtensionException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileExtensionException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileExtensionException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileExtensionException.java diff --git a/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileNameException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileNameException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileNameException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/customexception/IncorrectFileNameException.java diff --git a/core-java-lang/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/doubles/SplitFloatingPointNumbers.java diff --git a/core-java-lang/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/dynamicproxy/DynamicInvocationHandler.java diff --git a/core-java-lang/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/dynamicproxy/TimingDynamicInvocationHandler.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java new file mode 100644 index 0000000000..6c80adacb1 --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java new file mode 100644 index 0000000000..28bf3a475a --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java new file mode 100644 index 0000000000..cb98695de8 --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java new file mode 100644 index 0000000000..89c45f9d1b --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java new file mode 100644 index 0000000000..e41d6525f1 --- /dev/null +++ b/core-java-modules/core-java-lang/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-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java index 9690648386..32d88cfd12 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Exceptions.java @@ -1,212 +1,212 @@ -package com.baeldung.exceptionhandling; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Scanner; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -public class Exceptions { - - private final static Logger logger = Logger.getLogger("ExceptionLogging"); - - public static List getPlayers() throws IOException { - Path path = Paths.get("players.dat"); - List players = Files.readAllLines(path); - - return players.stream() - .map(Player::new) - .collect(Collectors.toList()); - } - - public List loadAllPlayers(String playersFile) throws IOException{ - try { - throw new IOException(); - } catch(IOException ex) { - throw new IllegalStateException(); - } - } - - public int getPlayerScoreThrows(String playerFile) throws FileNotFoundException { - Scanner contents = new Scanner(new File(playerFile)); - return Integer.parseInt(contents.nextLine()); - } - - public int getPlayerScoreTryCatch(String playerFile) { - try { - Scanner contents = new Scanner(new File(playerFile)); - return Integer.parseInt(contents.nextLine()); - } catch (FileNotFoundException noFile) { - throw new IllegalArgumentException("File not found"); - } - } - - public int getPlayerScoreTryCatchRecovery(String playerFile) { - try { - Scanner contents = new Scanner(new File(playerFile)); - return Integer.parseInt(contents.nextLine()); - } catch ( FileNotFoundException noFile ) { - logger.warning("File not found, resetting score."); - return 0; - } - } - - public int getPlayerScoreFinally(String playerFile) throws FileNotFoundException { - Scanner contents = null; - try { - contents = new Scanner(new File(playerFile)); - return Integer.parseInt(contents.nextLine()); - } finally { - if (contents != null) { - contents.close(); - } - } - } - - public int getPlayerScoreTryWithResources(String playerFile) { - try (Scanner contents = new Scanner(new File(playerFile))) { - return Integer.parseInt(contents.nextLine()); - } catch (FileNotFoundException e ) { - logger.warning("File not found, resetting score."); - return 0; - } - } - - public int getPlayerScoreMultipleCatchBlocks(String playerFile) { - try (Scanner contents = new Scanner(new File(playerFile))) { - return Integer.parseInt(contents.nextLine()); - } catch (IOException e) { - logger.warning("Player file wouldn't load!"); - return 0; - } catch (NumberFormatException e) { - logger.warning("Player file was corrupted!"); - return 0; - } - } - - public int getPlayerScoreMultipleCatchBlocksAlternative(String playerFile) { - try (Scanner contents = new Scanner(new File(playerFile)) ) { - return Integer.parseInt(contents.nextLine()); - } catch (FileNotFoundException e) { - logger.warning("Player file not found!"); - return 0; - } catch (IOException e) { - logger.warning("Player file wouldn't load!"); - return 0; - } catch (NumberFormatException e) { - logger.warning("Player file was corrupted!"); - return 0; - } - } - - public int getPlayerScoreUnionCatchBlocks(String playerFile) { - try (Scanner contents = new Scanner(new File(playerFile))) { - return Integer.parseInt(contents.nextLine()); - } catch (IOException | NumberFormatException e) { - logger.warning("Failed to load score!"); - return 0; - } - } - - public List loadAllPlayersThrowingChecked(String playersFile) throws TimeoutException { - boolean tooLong = true; - - while (!tooLong) { - // ... potentially long operation - } - throw new TimeoutException("This operation took too long"); - } - - public List loadAllPlayersThrowingUnchecked(String playersFile) throws TimeoutException { - if(!isFilenameValid(playersFile)) { - throw new IllegalArgumentException("Filename isn't valid!"); - } - return null; - - // ... - } - - public List loadAllPlayersWrapping(String playersFile) throws IOException { - try { - throw new IOException(); - } catch (IOException io) { - throw io; - } - } - - public List loadAllPlayersRethrowing(String playersFile) throws PlayerLoadException { - try { - throw new IOException(); - } catch (IOException io) { - throw new PlayerLoadException(io); - } - } - - public List loadAllPlayersThrowable(String playersFile) { - try { - throw new NullPointerException(); - } catch ( Throwable t ) { - throw t; - } - } - - class FewerExceptions extends Exceptions { - @Override - public List loadAllPlayers(String playersFile) { //can't add "throws MyCheckedException - return null; - // overridden - } - } - - public void throwAsGotoAntiPattern() throws MyException { - try { - // bunch of code - throw new MyException(); - // second bunch of code - } catch ( MyException e ) { - // third bunch of code - } - } - - public int getPlayerScoreSwallowingExceptionAntiPattern(String playerFile) { - try { - // ... - } catch (Exception e) {} // <== catch and swallow - return 0; - } - - public int getPlayerScoreSwallowingExceptionAntiPatternAlternative(String playerFile) { - try { - // ... - } catch (Exception e) { - e.printStackTrace(); - } - return 0; - } - - public int getPlayerScoreSwallowingExceptionAntiPatternAlternative2(String playerFile) throws PlayerScoreException { - try { - throw new IOException(); - } catch (IOException e) { - throw new PlayerScoreException(e); - } - } - - public int getPlayerScoreReturnInFinallyAntiPattern(String playerFile) { - int score = 0; - try { - throw new IOException(); - } finally { - return score; // <== the IOException is dropped - } - } - - private boolean isFilenameValid(String name) { - return false; - } -} +package com.baeldung.exceptionhandling; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Scanner; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class Exceptions { + + private final static Logger logger = Logger.getLogger("ExceptionLogging"); + + public static List getPlayers() throws IOException { + Path path = Paths.get("players.dat"); + List players = Files.readAllLines(path); + + return players.stream() + .map(Player::new) + .collect(Collectors.toList()); + } + + public List loadAllPlayers(String playersFile) throws IOException{ + try { + throw new IOException(); + } catch(IOException ex) { + throw new IllegalStateException(); + } + } + + public int getPlayerScoreThrows(String playerFile) throws FileNotFoundException { + Scanner contents = new Scanner(new File(playerFile)); + return Integer.parseInt(contents.nextLine()); + } + + public int getPlayerScoreTryCatch(String playerFile) { + try { + Scanner contents = new Scanner(new File(playerFile)); + return Integer.parseInt(contents.nextLine()); + } catch (FileNotFoundException noFile) { + throw new IllegalArgumentException("File not found"); + } + } + + public int getPlayerScoreTryCatchRecovery(String playerFile) { + try { + Scanner contents = new Scanner(new File(playerFile)); + return Integer.parseInt(contents.nextLine()); + } catch ( FileNotFoundException noFile ) { + logger.warning("File not found, resetting score."); + return 0; + } + } + + public int getPlayerScoreFinally(String playerFile) throws FileNotFoundException { + Scanner contents = null; + try { + contents = new Scanner(new File(playerFile)); + return Integer.parseInt(contents.nextLine()); + } finally { + if (contents != null) { + contents.close(); + } + } + } + + public int getPlayerScoreTryWithResources(String playerFile) { + try (Scanner contents = new Scanner(new File(playerFile))) { + return Integer.parseInt(contents.nextLine()); + } catch (FileNotFoundException e ) { + logger.warning("File not found, resetting score."); + return 0; + } + } + + public int getPlayerScoreMultipleCatchBlocks(String playerFile) { + try (Scanner contents = new Scanner(new File(playerFile))) { + return Integer.parseInt(contents.nextLine()); + } catch (IOException e) { + logger.warning("Player file wouldn't load!"); + return 0; + } catch (NumberFormatException e) { + logger.warning("Player file was corrupted!"); + return 0; + } + } + + public int getPlayerScoreMultipleCatchBlocksAlternative(String playerFile) { + try (Scanner contents = new Scanner(new File(playerFile)) ) { + return Integer.parseInt(contents.nextLine()); + } catch (FileNotFoundException e) { + logger.warning("Player file not found!"); + return 0; + } catch (IOException e) { + logger.warning("Player file wouldn't load!"); + return 0; + } catch (NumberFormatException e) { + logger.warning("Player file was corrupted!"); + return 0; + } + } + + public int getPlayerScoreUnionCatchBlocks(String playerFile) { + try (Scanner contents = new Scanner(new File(playerFile))) { + return Integer.parseInt(contents.nextLine()); + } catch (IOException | NumberFormatException e) { + logger.warning("Failed to load score!"); + return 0; + } + } + + public List loadAllPlayersThrowingChecked(String playersFile) throws TimeoutException { + boolean tooLong = true; + + while (!tooLong) { + // ... potentially long operation + } + throw new TimeoutException("This operation took too long"); + } + + public List loadAllPlayersThrowingUnchecked(String playersFile) throws TimeoutException { + if(!isFilenameValid(playersFile)) { + throw new IllegalArgumentException("Filename isn't valid!"); + } + return null; + + // ... + } + + public List loadAllPlayersWrapping(String playersFile) throws IOException { + try { + throw new IOException(); + } catch (IOException io) { + throw io; + } + } + + public List loadAllPlayersRethrowing(String playersFile) throws PlayerLoadException { + try { + throw new IOException(); + } catch (IOException io) { + throw new PlayerLoadException(io); + } + } + + public List loadAllPlayersThrowable(String playersFile) { + try { + throw new NullPointerException(); + } catch ( Throwable t ) { + throw t; + } + } + + class FewerExceptions extends Exceptions { + @Override + public List loadAllPlayers(String playersFile) { //can't add "throws MyCheckedException + return null; + // overridden + } + } + + public void throwAsGotoAntiPattern() throws MyException { + try { + // bunch of code + throw new MyException(); + // second bunch of code + } catch ( MyException e ) { + // third bunch of code + } + } + + public int getPlayerScoreSwallowingExceptionAntiPattern(String playerFile) { + try { + // ... + } catch (Exception e) {} // <== catch and swallow + return 0; + } + + public int getPlayerScoreSwallowingExceptionAntiPatternAlternative(String playerFile) { + try { + // ... + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + public int getPlayerScoreSwallowingExceptionAntiPatternAlternative2(String playerFile) throws PlayerScoreException { + try { + throw new IOException(); + } catch (IOException e) { + throw new PlayerScoreException(e); + } + } + + public int getPlayerScoreReturnInFinallyAntiPattern(String playerFile) { + int score = 0; + try { + throw new IOException(); + } finally { + return score; // <== the IOException is dropped + } + } + + private boolean isFilenameValid(String name) { + return false; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java similarity index 94% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java index 5a50acc4de..c2908b7278 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/MyException.java @@ -1,5 +1,5 @@ -package com.baeldung.exceptionhandling; - -public class MyException extends Throwable { - -} +package com.baeldung.exceptionhandling; + +public class MyException extends Throwable { + +} diff --git a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java similarity index 93% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java index 4efd37134f..e866802fe3 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/Player.java @@ -1,12 +1,12 @@ -package com.baeldung.exceptionhandling; - -public class Player { - - public int id; - public String name; - - public Player(String name) { - this.name = name; - } - -} +package com.baeldung.exceptionhandling; + +public class Player { + + public int id; + public String name; + + public Player(String name) { + this.name = name; + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java similarity index 94% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java index 5302fd8e7d..d92edeebbd 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerLoadException.java @@ -1,11 +1,11 @@ -package com.baeldung.exceptionhandling; - -import java.io.IOException; - -public class PlayerLoadException extends Exception { - - public PlayerLoadException(IOException io) { - super(io); - } - -} +package com.baeldung.exceptionhandling; + +import java.io.IOException; + +public class PlayerLoadException extends Exception { + + public PlayerLoadException(IOException io) { + super(io); + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java index d11159217e..299370ee86 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/PlayerScoreException.java @@ -1,8 +1,8 @@ -package com.baeldung.exceptionhandling; - -public class PlayerScoreException extends Exception { - - public PlayerScoreException(Exception e) { - super(e); - } -} +package com.baeldung.exceptionhandling; + +public class PlayerScoreException extends Exception { + + public PlayerScoreException(Exception e) { + super(e); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java index 294ad542d3..0211284e5d 100644 --- a/core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/exceptionhandling/TimeoutException.java @@ -1,8 +1,8 @@ -package com.baeldung.exceptionhandling; - -public class TimeoutException extends Exception { - - public TimeoutException(String message) { - super(message); - } -} +package com.baeldung.exceptionhandling; + +public class TimeoutException extends Exception { + + public TimeoutException(String message) { + super(message); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/finalize/CloseableResource.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/CloseableResource.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalize/CloseableResource.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/CloseableResource.java diff --git a/core-java-lang/src/main/java/com/baeldung/finalize/Finalizable.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/Finalizable.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/finalize/Finalizable.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/Finalizable.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java new file mode 100644 index 0000000000..0bb6560465 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java @@ -0,0 +1,5 @@ +package com.baeldung.interfaces; + +public interface Box extends HasColor { + int getHeight(); +} diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/CommaSeparatedCustomers.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/CommaSeparatedCustomers.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/interfaces/CommaSeparatedCustomers.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/CommaSeparatedCustomers.java diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/Customer.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Customer.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/interfaces/Customer.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Customer.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java new file mode 100644 index 0000000000..8c6bd3f7f3 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java @@ -0,0 +1,14 @@ +package com.baeldung.interfaces; + +public class Employee { + + private double salary; + + public double getSalary() { + return salary; + } + + public void setSalary(double salary) { + this.salary = salary; + } +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java new file mode 100644 index 0000000000..5c841b7c2b --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java @@ -0,0 +1,17 @@ +package com.baeldung.interfaces; + +import java.util.Comparator; + +public class EmployeeSalaryComparator implements Comparator { + + @Override + public int compare(Employee employeeA, Employee employeeB) { + if (employeeA.getSalary() < employeeB.getSalary()) { + return -1; + } else if (employeeA.getSalary() > employeeB.getSalary()) { + return 1; + } else { + return 0; + } + } +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java new file mode 100644 index 0000000000..d9688ea866 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java @@ -0,0 +1,4 @@ +package com.baeldung.interfaces; + +public interface HasColor { +} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java similarity index 83% rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java index fb0d36e3e0..d9b30a1e7b 100644 --- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java @@ -1,6 +1,7 @@ package com.baeldung.interfaces.multiinheritance; -public class Vehicle implements Fly, Transform { +public class Car implements Fly,Transform { + @Override public void fly() { System.out.println("I can Fly!!"); diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java similarity index 69% rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java index d84182aec6..611e51c67b 100644 --- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java @@ -1,5 +1,6 @@ package com.baeldung.interfaces.multiinheritance; -public abstract interface Fly{ +public interface Fly { + void fly(); } diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java similarity index 52% rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java index a18bbafdc1..8bdba43a05 100644 --- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java @@ -1,5 +1,10 @@ package com.baeldung.interfaces.multiinheritance; public interface Transform { + void transform(); + + default void printSpecs(){ + System.out.println("Transform Specification"); + } } diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java new file mode 100644 index 0000000000..be25e112ee --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java @@ -0,0 +1,4 @@ +package com.baeldung.interfaces.multiinheritance; + +public abstract class Vehicle implements Transform { +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java new file mode 100644 index 0000000000..b4d97bd53a --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java @@ -0,0 +1,9 @@ +package com.baeldung.interfaces.polymorphysim; + +public class Circle implements Shape { + + @Override + public String name() { + return "Circle"; + } +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java new file mode 100644 index 0000000000..5cce3c3af0 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java @@ -0,0 +1,20 @@ +package com.baeldung.interfaces.polymorphysim; + +import java.util.ArrayList; +import java.util.List; + +public class MainTestClass { + + public static void main(String[] args) { + List shapes = new ArrayList<>(); + Shape circleShape = new Circle(); + Shape squareShape = new Square(); + + shapes.add(circleShape); + shapes.add(squareShape); + + for (Shape shape : shapes) { + System.out.println(shape.name()); + } + } +} diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java similarity index 51% rename from core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java index fcb0c65e7b..885dc73de2 100644 --- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java @@ -1,6 +1,6 @@ package com.baeldung.interfaces.polymorphysim; public interface Shape { - public abstract String name(); - public abstract double area(); + + String name(); } diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java new file mode 100644 index 0000000000..c17bdd902d --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java @@ -0,0 +1,9 @@ +package com.baeldung.interfaces.polymorphysim; + +public class Square implements Shape { + + @Override + public String name() { + return "Square"; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Animal.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Animal.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Animal.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Animal.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Bird.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Bird.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Bird.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Bird.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/DynamicGreeter.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/DynamicGreeter.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/DynamicGreeter.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/DynamicGreeter.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Eating.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Eating.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Eating.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Eating.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Goat.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Goat.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Goat.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Goat.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Greeter.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Greeter.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Greeter.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Greeter.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/GreetingAnnotation.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/GreetingAnnotation.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/GreetingAnnotation.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/GreetingAnnotation.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Greetings.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Greetings.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Greetings.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Greetings.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Locomotion.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Locomotion.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Locomotion.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Locomotion.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Operations.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Operations.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Operations.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Operations.java diff --git a/core-java-lang/src/main/java/com/baeldung/java/reflection/Person.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Person.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/java/reflection/Person.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/java/reflection/Person.java diff --git a/core-java-lang/src/main/java/com/baeldung/keywords/finalize/FinalizeObject.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalize/FinalizeObject.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keywords/finalize/FinalizeObject.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalize/FinalizeObject.java diff --git a/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Child.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Child.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Child.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Child.java diff --git a/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/GrandChild.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/GrandChild.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/GrandChild.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/GrandChild.java diff --git a/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Parent.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Parent.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Parent.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finalkeyword/Parent.java diff --git a/core-java-lang/src/main/java/com/baeldung/keywords/finallykeyword/FinallyExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finallykeyword/FinallyExample.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/keywords/finallykeyword/FinallyExample.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/keywords/finallykeyword/FinallyExample.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java new file mode 100644 index 0000000000..0762b0eb8a --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java @@ -0,0 +1,10 @@ +package com.baeldung.nativekeyword; + +public class DateTimeUtils { + + public native String getSystemTime(); + + static { + System.loadLibrary("nativedatetimeutils"); + } +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java new file mode 100644 index 0000000000..76fe548ed3 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java @@ -0,0 +1,11 @@ +package com.baeldung.nativekeyword; + +import com.baeldung.nativekeyword.DateTimeUtils; + +public class NativeMainApp { + public static void main(String[] args) { + DateTimeUtils dateTimeUtils = new DateTimeUtils(); + String input = dateTimeUtils.getSystemTime(); + System.out.println("System time is : " + input); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java index 2b19f3496d..b5b357a322 100644 --- a/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/ClassWithInitErrors.java @@ -1,5 +1,5 @@ -package com.baeldung.noclassdeffounderror; - -public class ClassWithInitErrors { - static int data = 1 / 0; -} +package com.baeldung.noclassdeffounderror; + +public class ClassWithInitErrors { + static int data = 1 / 0; +} diff --git a/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java index 0d02391a73..7bcefbdbd3 100644 --- a/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorExample.java @@ -1,14 +1,14 @@ -package com.baeldung.noclassdeffounderror; - -public class NoClassDefFoundErrorExample { - public ClassWithInitErrors getClassWithInitErrors() { - ClassWithInitErrors test; - try { - test = new ClassWithInitErrors(); - } catch (Throwable t) { - System.out.println(t); - } - test = new ClassWithInitErrors(); - return test; - } +package com.baeldung.noclassdeffounderror; + +public class NoClassDefFoundErrorExample { + public ClassWithInitErrors getClassWithInitErrors() { + ClassWithInitErrors test; + try { + test = new ClassWithInitErrors(); + } catch (Throwable t) { + System.out.println(t); + } + test = new ClassWithInitErrors(); + return test; + } } \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/objects/Car.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/objects/Car.java new file mode 100644 index 0000000000..35ef8585b2 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/objects/Car.java @@ -0,0 +1,51 @@ +package com.baeldung.objects; + +public class Car { + + private String type; + private String model; + private String color; + private int speed; + + public Car(String type, String model, String color) { + this.type = type; + this.model = model; + this.color = color; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public int getSpeed() { + return speed; + } + + public int increaseSpeed(int increment) { + if (increment > 0) { + this.speed += increment; + } else { + System.out.println("Increment can't be negative."); + } + return this.speed; + } + + public int decreaseSpeed(int decrement) { + if (decrement > 0 && decrement <= this.speed) { + this.speed -= decrement; + } else { + System.out.println("Decrement can't be negative or greater than current speed."); + } + return this.speed; + } + + @Override + public String toString() { + return "Car [type=" + type + ", model=" + model + ", color=" + color + ", speed=" + speed + "]"; + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/packages/TodoApp.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/TodoApp.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/packages/TodoApp.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/TodoApp.java diff --git a/core-java-lang/src/main/java/com/baeldung/packages/TodoList.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/TodoList.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/packages/TodoList.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/TodoList.java diff --git a/core-java-lang/src/main/java/com/baeldung/packages/domain/TodoItem.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/domain/TodoItem.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/packages/domain/TodoItem.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/packages/domain/TodoItem.java diff --git a/core-java-lang/src/main/java/com/baeldung/parameterpassing/NonPrimitives.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/parameterpassing/NonPrimitives.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/parameterpassing/NonPrimitives.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/parameterpassing/NonPrimitives.java diff --git a/core-java-lang/src/main/java/com/baeldung/parameterpassing/Primitives.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/parameterpassing/Primitives.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/parameterpassing/Primitives.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/parameterpassing/Primitives.java diff --git a/core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java index 0c3f0ecc40..c5dd746a4c 100644 --- a/core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/BinaryNode.java @@ -1,31 +1,31 @@ -package com.baeldung.recursion; - -public class BinaryNode { - int value; - BinaryNode left; - BinaryNode right; - - public BinaryNode(int value){ - this.value = value; - } - - public int getValue() { - return value; - } - public void setValue(int value) { - this.value = value; - } - public BinaryNode getLeft() { - return left; - } - public void setLeft(BinaryNode left) { - this.left = left; - } - public BinaryNode getRight() { - return right; - } - public void setRight(BinaryNode right) { - this.right = right; - } - -} +package com.baeldung.recursion; + +public class BinaryNode { + int value; + BinaryNode left; + BinaryNode right; + + public BinaryNode(int value){ + this.value = value; + } + + public int getValue() { + return value; + } + public void setValue(int value) { + this.value = value; + } + public BinaryNode getLeft() { + return left; + } + public void setLeft(BinaryNode left) { + this.left = left; + } + public BinaryNode getRight() { + return right; + } + public void setRight(BinaryNode right) { + this.right = right; + } + +} diff --git a/core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java index 649c0e0587..b6800d2e7e 100644 --- a/core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/recursion/RecursionExample.java @@ -1,64 +1,64 @@ -package com.baeldung.recursion; - -public class RecursionExample { - - public int sum(int n){ - if (n >= 1){ - return sum(n - 1) + n; - } - return n; - } - - public int tailSum(int currentSum, int n){ - if (n <= 1) { - return currentSum + n; - } - return tailSum(currentSum + n, n - 1); - } - - public int iterativeSum(int n){ - int sum = 0; - if(n < 0){ - return -1; - } - for(int i=0; i<=n; i++){ - sum += i; - } - return sum; - } - - public int powerOf10(int n){ - if (n == 0){ - return 1; - } - return powerOf10(n-1)*10; - } - - public int fibonacci(int n){ - if (n <=1 ){ - return n; - } - return fibonacci(n-1) + fibonacci(n-2); - } - - public String toBinary(int n){ - if (n <= 1 ){ - return String.valueOf(n); - } - return toBinary(n / 2) + String.valueOf(n % 2); - } - - public int calculateTreeHeight(BinaryNode root){ - if (root!= null){ - if (root.getLeft() != null || root.getRight() != null){ - return 1 + max(calculateTreeHeight(root.left) , calculateTreeHeight(root.right)); - } - } - return 0; - } - - public int max(int a,int b){ - return a>b ? a:b; - } - -} +package com.baeldung.recursion; + +public class RecursionExample { + + public int sum(int n){ + if (n >= 1){ + return sum(n - 1) + n; + } + return n; + } + + public int tailSum(int currentSum, int n){ + if (n <= 1) { + return currentSum + n; + } + return tailSum(currentSum + n, n - 1); + } + + public int iterativeSum(int n){ + int sum = 0; + if(n < 0){ + return -1; + } + for(int i=0; i<=n; i++){ + sum += i; + } + return sum; + } + + public int powerOf10(int n){ + if (n == 0){ + return 1; + } + return powerOf10(n-1)*10; + } + + public int fibonacci(int n){ + if (n <=1 ){ + return n; + } + return fibonacci(n-1) + fibonacci(n-2); + } + + public String toBinary(int n){ + if (n <= 1 ){ + return String.valueOf(n); + } + return toBinary(n / 2) + String.valueOf(n % 2); + } + + public int calculateTreeHeight(BinaryNode root){ + if (root!= null){ + if (root.getLeft() != null || root.getRight() != null){ + return 1 + max(calculateTreeHeight(root.left) , calculateTreeHeight(root.right)); + } + } + return 0; + } + + public int max(int a,int b){ + return a>b ? a:b; + } + +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java new file mode 100644 index 0000000000..8deec35c16 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java @@ -0,0 +1,14 @@ +package com.baeldung.scope; + +public class BracketScopeExample { + + public void mathOperationExample() { + Integer sum = 0; + { + Integer number = 2; + sum = sum + number; + } + // compiler error, number cannot be solved as a variable + // number++; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java new file mode 100644 index 0000000000..c81fcc9550 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java @@ -0,0 +1,14 @@ +package com.baeldung.scope; + +public class ClassScopeExample { + + Integer amount = 0; + + public void exampleMethod() { + amount++; + } + + public void anotherExampleMethod() { + Integer anotherAmount = amount + 4; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java new file mode 100644 index 0000000000..be41252623 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -0,0 +1,18 @@ +package com.baeldung.scope; + +import java.util.Arrays; +import java.util.List; + +public class LoopScopeExample { + + List listOfNames = Arrays.asList("Joe", "Susan", "Pattrick"); + + public void iterationOfNames() { + String allNames = ""; + for (String name : listOfNames) { + allNames = allNames + " " + name; + } + // compiler error, name cannot be resolved to a variable + // String lastNameUsed = name; + } +} diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java new file mode 100644 index 0000000000..63a6a25271 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java @@ -0,0 +1,13 @@ +package com.baeldung.scope; + +public class MethodScopeExample { + + public void methodA() { + Integer area = 2; + } + + public void methodB() { + // compiler error, area cannot be resolved to a variable + // area = area + 2; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java new file mode 100644 index 0000000000..c3c5bec221 --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java @@ -0,0 +1,12 @@ +package com.baeldung.scope; + +public class NestedScopesExample { + + String title = "Baeldung"; + + public void printTitle() { + System.out.println(title); + String title = "John Doe"; + System.out.println(title); + } +} \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyRunnable.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyRunnable.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyRunnable.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyRunnable.java diff --git a/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyThrows.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyThrows.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyThrows.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/sneakythrows/SneakyThrows.java diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java index 9555433792..91b8a3bbb0 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/AccountHolder.java @@ -1,8 +1,8 @@ -package com.baeldung.stackoverflowerror; - -public class AccountHolder { - private String firstName; - private String lastName; - - AccountHolder jointAccountHolder = new AccountHolder(); -} +package com.baeldung.stackoverflowerror; + +public class AccountHolder { + private String firstName; + private String lastName; + + AccountHolder jointAccountHolder = new AccountHolder(); +} diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java index 99ef2b4f92..3b95fd1368 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassOne.java @@ -1,16 +1,16 @@ -package com.baeldung.stackoverflowerror; - -public class ClassOne { - private int oneValue; - private ClassTwo clsTwoInstance = null; - - public ClassOne() { - oneValue = 0; - clsTwoInstance = new ClassTwo(); - } - - public ClassOne(int oneValue, ClassTwo clsTwoInstance) { - this.oneValue = oneValue; - this.clsTwoInstance = clsTwoInstance; - } -} +package com.baeldung.stackoverflowerror; + +public class ClassOne { + private int oneValue; + private ClassTwo clsTwoInstance = null; + + public ClassOne() { + oneValue = 0; + clsTwoInstance = new ClassTwo(); + } + + public ClassOne(int oneValue, ClassTwo clsTwoInstance) { + this.oneValue = oneValue; + this.clsTwoInstance = clsTwoInstance; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java similarity index 95% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java index 0d34ac3c32..0adf075b43 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/ClassTwo.java @@ -1,16 +1,16 @@ -package com.baeldung.stackoverflowerror; - -public class ClassTwo { - private int twoValue; - private ClassOne clsOneInstance = null; - - public ClassTwo() { - twoValue = 10; - clsOneInstance = new ClassOne(); - } - - public ClassTwo(int twoValue, ClassOne clsOneInstance) { - this.twoValue = twoValue; - this.clsOneInstance = clsOneInstance; - } -} +package com.baeldung.stackoverflowerror; + +public class ClassTwo { + private int twoValue; + private ClassOne clsOneInstance = null; + + public ClassTwo() { + twoValue = 10; + clsOneInstance = new ClassOne(); + } + + public ClassTwo(int twoValue, ClassOne clsOneInstance) { + this.twoValue = twoValue; + this.clsOneInstance = clsOneInstance; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java similarity index 97% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java index 9fb00d4b83..c67eeb30d1 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationCondition.java @@ -1,7 +1,7 @@ -package com.baeldung.stackoverflowerror; - -public class InfiniteRecursionWithTerminationCondition { - public int calculateFactorial(final int number) { - return number == 1 ? 1 : number * calculateFactorial(number - 1); - } -} +package com.baeldung.stackoverflowerror; + +public class InfiniteRecursionWithTerminationCondition { + public int calculateFactorial(final int number) { + return number == 1 ? 1 : number * calculateFactorial(number - 1); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java similarity index 97% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java index 16d771f389..8d10c65dcc 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationCondition.java @@ -1,7 +1,7 @@ -package com.baeldung.stackoverflowerror; - -public class RecursionWithCorrectTerminationCondition { - public int calculateFactorial(final int number) { - return number <= 1 ? 1 : number * calculateFactorial(number - 1); - } -} +package com.baeldung.stackoverflowerror; + +public class RecursionWithCorrectTerminationCondition { + public int calculateFactorial(final int number) { + return number <= 1 ? 1 : number * calculateFactorial(number - 1); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java similarity index 96% rename from core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java index f5160c3eb3..0b7fb3cf94 100644 --- a/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursion.java @@ -1,7 +1,7 @@ -package com.baeldung.stackoverflowerror; - -public class UnintendedInfiniteRecursion { - public int calculateFactorial(int number) { - return number * calculateFactorial(number - 1); - } -} +package com.baeldung.stackoverflowerror; + +public class UnintendedInfiniteRecursion { + public int calculateFactorial(int number) { + return number * calculateFactorial(number - 1); + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/synthetic/BridgeMethodDemo.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/BridgeMethodDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/synthetic/BridgeMethodDemo.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/BridgeMethodDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticConstructorDemo.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticConstructorDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticConstructorDemo.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticConstructorDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticFieldDemo.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticFieldDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticFieldDemo.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticFieldDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticMethodDemo.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticMethodDemo.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticMethodDemo.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/synthetic/SyntheticMethodDemo.java diff --git a/core-java-lang/src/main/java/com/baeldung/throwsexception/DataAccessException.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/DataAccessException.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/throwsexception/DataAccessException.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/DataAccessException.java diff --git a/core-java-lang/src/main/java/com/baeldung/throwsexception/Main.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/Main.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/throwsexception/Main.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/Main.java diff --git a/core-java-lang/src/main/java/com/baeldung/throwsexception/PersonRepository.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/PersonRepository.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/throwsexception/PersonRepository.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/PersonRepository.java diff --git a/core-java-lang/src/main/java/com/baeldung/throwsexception/SimpleService.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/SimpleService.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/throwsexception/SimpleService.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/SimpleService.java diff --git a/core-java-lang/src/main/java/com/baeldung/throwsexception/TryCatch.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/TryCatch.java similarity index 100% rename from core-java-lang/src/main/java/com/baeldung/throwsexception/TryCatch.java rename to core-java-modules/core-java-lang/src/main/java/com/baeldung/throwsexception/TryCatch.java diff --git a/core-java-lang/src/main/resources/file.txt b/core-java-modules/core-java-lang/src/main/resources/file.txt similarity index 100% rename from core-java-lang/src/main/resources/file.txt rename to core-java-modules/core-java-lang/src/main/resources/file.txt diff --git a/core-java-lang/src/test/java/com/baeldung/binding/AnimalActivityUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/AnimalActivityUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/binding/AnimalActivityUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/AnimalActivityUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/binding/AnimalUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/AnimalUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/binding/AnimalUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/AnimalUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/binding/CatUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/CatUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/binding/CatUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/binding/CatUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java index b076b0324a..59605fb1c9 100644 --- a/core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/classnotfoundexception/ClassNotFoundExceptionUnitTest.java @@ -1,11 +1,11 @@ -package com.baeldung.classnotfoundexception; - -import org.junit.Test; - -public class ClassNotFoundExceptionUnitTest { - - @Test(expected = ClassNotFoundException.class) - public void givenNoDriversInClassPath_whenLoadDrivers_thenClassNotFoundException() throws ClassNotFoundException { - Class.forName("oracle.jdbc.driver.OracleDriver"); - } +package com.baeldung.classnotfoundexception; + +import org.junit.Test; + +public class ClassNotFoundExceptionUnitTest { + + @Test(expected = ClassNotFoundException.class) + public void givenNoDriversInClassPath_whenLoadDrivers_thenClassNotFoundException() throws ClassNotFoundException { + Class.forName("oracle.jdbc.driver.OracleDriver"); + } } \ No newline at end of file diff --git a/core-java-lang/src/test/java/com/baeldung/comparable/ComparableUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparable/ComparableUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/comparable/ComparableUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/comparable/ComparableUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/comparator/ComparatorUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/ComparatorUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/comparator/ComparatorUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/ComparatorUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/compoundoperators/CompoundOperatorsUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/compoundoperators/CompoundOperatorsUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/compoundoperators/CompoundOperatorsUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/compoundoperators/CompoundOperatorsUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileExtensionExceptionUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileExtensionExceptionUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileExtensionExceptionUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileExtensionExceptionUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileNameExceptionUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileNameExceptionUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileNameExceptionUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/customexception/IncorrectFileNameExceptionUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/dynamicproxy/DynamicProxyIntegrationTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/dynamicproxy/DynamicProxyIntegrationTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/dynamicproxy/DynamicProxyIntegrationTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/dynamicproxy/DynamicProxyIntegrationTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java new file mode 100644 index 0000000000..ab3e684230 --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java new file mode 100644 index 0000000000..02995a2f41 --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java new file mode 100644 index 0000000000..40c76a97b1 --- /dev/null +++ b/core-java-modules/core-java-lang/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-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java new file mode 100644 index 0000000000..d349dcef72 --- /dev/null +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java @@ -0,0 +1,71 @@ +/* + * 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()) { + assertSame(e4, Element4.valueOfLabel(e4.label)); + } + } + + @Test + public void whenLocatebyAtmNum_thenReturnCorrectValue() { + for (Element4 e4 : Element4.values()) { + assertSame(e4, Element4.valueOfAtomicNumber(e4.atomicNumber)); + } + } + + @Test + public void whenLocatebyAtmWt_thenReturnCorrectValue() { + for (Element4 e4 : Element4.values()) { + assertSame(e4, Element4.valueOfAtomicWeight(e4.atomicWeight)); + } + } + + /** + * Test of toString method, of class Element4. + */ + @Test + public void whenCallingToString_thenReturnLabel() { + for (Element4 e4 : Element4.values()) { + assertEquals(e4.label, e4.toString()); + } + } + +} diff --git a/core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java index b3f585cfe4..29c690133d 100644 --- a/core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/exceptionhandling/ExceptionsUnitTest.java @@ -1,80 +1,80 @@ -package com.baeldung.exceptionhandling; - -import org.junit.Test; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.NoSuchFileException; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class ExceptionsUnitTest { - - Exceptions exceptions = new Exceptions(); - - @Test - public void getPlayers() { - assertThatThrownBy(() -> exceptions.getPlayers()) - .isInstanceOf(NoSuchFileException.class); - } - - @Test - public void loadAllPlayers() { - assertThatThrownBy(() -> exceptions.loadAllPlayers("")) - .isInstanceOf(IllegalStateException.class); - } - - @Test - public void getPlayerScoreThrows() { - assertThatThrownBy(() -> exceptions.getPlayerScoreThrows("")) - .isInstanceOf(FileNotFoundException.class); - } - - @Test - public void getPlayerScoreTryCatch() { - assertThatThrownBy(() -> exceptions.getPlayerScoreTryCatch("")) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - public void getPlayerScoreFinally() { - assertThatThrownBy(() -> exceptions.getPlayerScoreFinally("")) - .isInstanceOf(FileNotFoundException.class); - } - - @Test - public void loadAllPlayersThrowingChecked() { - assertThatThrownBy(() -> exceptions.loadAllPlayersThrowingChecked("")) - .isInstanceOf(TimeoutException.class); - } - - @Test - public void loadAllPlayersThrowingUnchecked() { - assertThatThrownBy(() -> exceptions.loadAllPlayersThrowingUnchecked("")) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - public void loadAllPlayersWrapping() { - assertThatThrownBy(() -> exceptions.loadAllPlayersWrapping("")) - .isInstanceOf(IOException.class); - } - - @Test - public void loadAllPlayersRethrowing() { - assertThatThrownBy(() -> exceptions.loadAllPlayersRethrowing("")) - .isInstanceOf(PlayerLoadException.class); - } - - @Test - public void loadAllPlayersThrowable() { - assertThatThrownBy(() -> exceptions.loadAllPlayersThrowable("")) - .isInstanceOf(NullPointerException.class); - } - - @Test - public void getPlayerScoreSwallowingExceptionAntiPatternAlternative2() { - assertThatThrownBy(() -> exceptions.getPlayerScoreSwallowingExceptionAntiPatternAlternative2("")) - .isInstanceOf(PlayerScoreException.class); - } -} +package com.baeldung.exceptionhandling; + +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.NoSuchFileException; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class ExceptionsUnitTest { + + Exceptions exceptions = new Exceptions(); + + @Test + public void getPlayers() { + assertThatThrownBy(() -> exceptions.getPlayers()) + .isInstanceOf(NoSuchFileException.class); + } + + @Test + public void loadAllPlayers() { + assertThatThrownBy(() -> exceptions.loadAllPlayers("")) + .isInstanceOf(IllegalStateException.class); + } + + @Test + public void getPlayerScoreThrows() { + assertThatThrownBy(() -> exceptions.getPlayerScoreThrows("")) + .isInstanceOf(FileNotFoundException.class); + } + + @Test + public void getPlayerScoreTryCatch() { + assertThatThrownBy(() -> exceptions.getPlayerScoreTryCatch("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void getPlayerScoreFinally() { + assertThatThrownBy(() -> exceptions.getPlayerScoreFinally("")) + .isInstanceOf(FileNotFoundException.class); + } + + @Test + public void loadAllPlayersThrowingChecked() { + assertThatThrownBy(() -> exceptions.loadAllPlayersThrowingChecked("")) + .isInstanceOf(TimeoutException.class); + } + + @Test + public void loadAllPlayersThrowingUnchecked() { + assertThatThrownBy(() -> exceptions.loadAllPlayersThrowingUnchecked("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void loadAllPlayersWrapping() { + assertThatThrownBy(() -> exceptions.loadAllPlayersWrapping("")) + .isInstanceOf(IOException.class); + } + + @Test + public void loadAllPlayersRethrowing() { + assertThatThrownBy(() -> exceptions.loadAllPlayersRethrowing("")) + .isInstanceOf(PlayerLoadException.class); + } + + @Test + public void loadAllPlayersThrowable() { + assertThatThrownBy(() -> exceptions.loadAllPlayersThrowable("")) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void getPlayerScoreSwallowingExceptionAntiPatternAlternative2() { + assertThatThrownBy(() -> exceptions.getPlayerScoreSwallowingExceptionAntiPatternAlternative2("")) + .isInstanceOf(PlayerScoreException.class); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/finalize/FinalizeUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/finalize/FinalizeUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/finalize/FinalizeUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/finalize/FinalizeUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/interfaces/InnerInterfaceUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/interfaces/InnerInterfaceUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/interfaces/InnerInterfaceUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/interfaces/InnerInterfaceUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/enumiteration/DaysOfWeekEnum.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/enumiteration/DaysOfWeekEnum.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/enumiteration/DaysOfWeekEnum.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/java/enumiteration/DaysOfWeekEnum.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java new file mode 100644 index 0000000000..110943e39f --- /dev/null +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/enumiteration/EnumIterationExamples.java @@ -0,0 +1,43 @@ +package com.baeldung.java.enumiteration; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + + +public class EnumIterationExamples { + public static void main(String[] args) { + System.out.println("Enum iteration using EnumSet:"); + EnumSet.allOf(DaysOfWeekEnum.class).forEach(day -> System.out.println(day)); + + System.out.println("Enum iteration using Stream:"); + DaysOfWeekEnum.stream().filter(d -> d.getTypeOfDay().equals("off")).forEach(System.out::println); + + System.out.println("Enum iteration using a for loop:"); + for (DaysOfWeekEnum day : DaysOfWeekEnum.values()) { + System.out.println(day); + } + + System.out.println("Enum iteration using Arrays.asList():"); + Arrays.asList(DaysOfWeekEnum.values()).forEach(day -> System.out.println(day)); + + System.out.println("Add Enum values to ArrayList:"); + List days = new ArrayList<>(); + days.add(DaysOfWeekEnum.FRIDAY); + days.add(DaysOfWeekEnum.SATURDAY); + days.add(DaysOfWeekEnum.SUNDAY); + for (DaysOfWeekEnum day : days) { + System.out.println(day); + } + System.out.println("Remove SATURDAY from the list:"); + days.remove(DaysOfWeekEnum.SATURDAY); + if (!days.contains(DaysOfWeekEnum.SATURDAY)) { + System.out.println("Saturday is no longer in the list"); + } + for (DaysOfWeekEnum day : days) { + System.out.println(day); + } + + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/java/reflection/OperationsUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/reflection/OperationsUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/reflection/OperationsUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/java/reflection/OperationsUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/java/reflection/ReflectionUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/java/reflection/ReflectionUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/java/reflection/ReflectionUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/java/reflection/ReflectionUnitTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java new file mode 100644 index 0000000000..ac27c11c68 --- /dev/null +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java @@ -0,0 +1,27 @@ +package com.baeldung.nativekeyword; + +import static org.junit.Assert.assertNotNull; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; + +public class DateTimeUtilsManualTest { + + private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(DateTimeUtilsManualTest.class); + + @BeforeClass + public static void setUpClass() { + System.loadLibrary("msvcr100"); + System.loadLibrary("libgcc_s_sjlj-1"); + System.loadLibrary("libstdc++-6"); + System.loadLibrary("nativedatetimeutils"); + } + + @Test + public void givenNativeLibsLoaded_thenNativeMethodIsAccessible() { + DateTimeUtils dateTimeUtils = new DateTimeUtils(); + LOG.info("System time is : " + dateTimeUtils.getSystemTime()); + assertNotNull(dateTimeUtils.getSystemTime()); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/nestedclass/AnonymousInner.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/AnonymousInner.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/nestedclass/AnonymousInner.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/AnonymousInner.java diff --git a/core-java-lang/src/test/java/com/baeldung/nestedclass/Enclosing.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/Enclosing.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/nestedclass/Enclosing.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/Enclosing.java diff --git a/core-java-lang/src/test/java/com/baeldung/nestedclass/NewEnclosing.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/NewEnclosing.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/nestedclass/NewEnclosing.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/NewEnclosing.java diff --git a/core-java-lang/src/test/java/com/baeldung/nestedclass/NewOuter.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/NewOuter.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/nestedclass/NewOuter.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/NewOuter.java diff --git a/core-java-lang/src/test/java/com/baeldung/nestedclass/Outer.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/Outer.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/nestedclass/Outer.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/nestedclass/Outer.java diff --git a/core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java index ccc8c1f69c..521c50098a 100644 --- a/core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/noclassdeffounderror/NoClassDefFoundErrorUnitTest.java @@ -1,12 +1,12 @@ -package com.baeldung.noclassdeffounderror; - -import org.junit.Test; - -public class NoClassDefFoundErrorUnitTest { - - @Test(expected = NoClassDefFoundError.class) - public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() { - NoClassDefFoundErrorExample sample = new NoClassDefFoundErrorExample(); - sample.getClassWithInitErrors(); - } +package com.baeldung.noclassdeffounderror; + +import org.junit.Test; + +public class NoClassDefFoundErrorUnitTest { + + @Test(expected = NoClassDefFoundError.class) + public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() { + NoClassDefFoundErrorExample sample = new NoClassDefFoundErrorExample(); + sample.getClassWithInitErrors(); + } } \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java new file mode 100644 index 0000000000..a1ef20523e --- /dev/null +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.objects; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +public class CarUnitTest { + + private Car car; + + @Before + public void setUp() throws Exception { + car = new Car("Ford", "Focus", "red"); + } + + @Test + public final void when_speedIncreased_then_verifySpeed() { + car.increaseSpeed(30); + assertEquals(30, car.getSpeed()); + + car.increaseSpeed(20); + assertEquals(50, car.getSpeed()); + } + + @Test + public final void when_speedDecreased_then_verifySpeed() { + car.increaseSpeed(50); + assertEquals(50, car.getSpeed()); + + car.decreaseSpeed(30); + assertEquals(20, car.getSpeed()); + + car.decreaseSpeed(20); + assertEquals(0, car.getSpeed()); + } + +} diff --git a/core-java-lang/src/test/java/com/baeldung/packages/PackagesUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/packages/PackagesUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/packages/PackagesUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/packages/PackagesUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java index 6c560c9c37..7b11e968ce 100644 --- a/core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/recursion/RecursionExampleUnitTest.java @@ -1,61 +1,61 @@ -package com.baeldung.recursion; - -import org.junit.Assert; -import org.junit.Test; - -public class RecursionExampleUnitTest { - - RecursionExample recursion = new RecursionExample(); - - @Test - public void testPowerOf10() { - int p0 = recursion.powerOf10(0); - int p1 = recursion.powerOf10(1); - int p4 = recursion.powerOf10(4); - - Assert.assertEquals(1, p0); - Assert.assertEquals(10, p1); - Assert.assertEquals(10000, p4); - } - - @Test - public void testFibonacci() { - int n0 = recursion.fibonacci(0); - int n1 = recursion.fibonacci(1); - int n7 = recursion.fibonacci(7); - - Assert.assertEquals(0, n0); - Assert.assertEquals(1, n1); - Assert.assertEquals(13, n7); - } - - @Test - public void testToBinary() { - String b0 = recursion.toBinary(0); - String b1 = recursion.toBinary(1); - String b10 = recursion.toBinary(10); - - Assert.assertEquals("0", b0); - Assert.assertEquals("1", b1); - Assert.assertEquals("1010", b10); - } - - @Test - public void testCalculateTreeHeight() { - BinaryNode root = new BinaryNode(1); - root.setLeft(new BinaryNode(1)); - root.setRight(new BinaryNode(1)); - - root.getLeft().setLeft(new BinaryNode(1)); - root.getLeft().getLeft().setRight(new BinaryNode(1)); - root.getLeft().getLeft().getRight().setLeft(new BinaryNode(1)); - - root.getRight().setLeft(new BinaryNode(1)); - root.getRight().getLeft().setRight(new BinaryNode(1)); - - int height = recursion.calculateTreeHeight(root); - - Assert.assertEquals(4, height); - } - -} +package com.baeldung.recursion; + +import org.junit.Assert; +import org.junit.Test; + +public class RecursionExampleUnitTest { + + RecursionExample recursion = new RecursionExample(); + + @Test + public void testPowerOf10() { + int p0 = recursion.powerOf10(0); + int p1 = recursion.powerOf10(1); + int p4 = recursion.powerOf10(4); + + Assert.assertEquals(1, p0); + Assert.assertEquals(10, p1); + Assert.assertEquals(10000, p4); + } + + @Test + public void testFibonacci() { + int n0 = recursion.fibonacci(0); + int n1 = recursion.fibonacci(1); + int n7 = recursion.fibonacci(7); + + Assert.assertEquals(0, n0); + Assert.assertEquals(1, n1); + Assert.assertEquals(13, n7); + } + + @Test + public void testToBinary() { + String b0 = recursion.toBinary(0); + String b1 = recursion.toBinary(1); + String b10 = recursion.toBinary(10); + + Assert.assertEquals("0", b0); + Assert.assertEquals("1", b1); + Assert.assertEquals("1010", b10); + } + + @Test + public void testCalculateTreeHeight() { + BinaryNode root = new BinaryNode(1); + root.setLeft(new BinaryNode(1)); + root.setRight(new BinaryNode(1)); + + root.getLeft().setLeft(new BinaryNode(1)); + root.getLeft().getLeft().setRight(new BinaryNode(1)); + root.getLeft().getLeft().getRight().setLeft(new BinaryNode(1)); + + root.getRight().setLeft(new BinaryNode(1)); + root.getRight().getLeft().setRight(new BinaryNode(1)); + + int height = recursion.calculateTreeHeight(root); + + Assert.assertEquals(4, height); + } + +} diff --git a/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyRunnableUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyRunnableUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyRunnableUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyRunnableUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyThrowsUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyThrowsUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyThrowsUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/sneakythrows/SneakyThrowsUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java index e6a8f89a16..180b7723ac 100644 --- a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/AccountHolderManualTest.java @@ -1,10 +1,10 @@ -package com.baeldung.stackoverflowerror; - -import org.junit.Test; - -public class AccountHolderManualTest { - @Test(expected = StackOverflowError.class) - public void whenInstanciatingAccountHolder_thenThrowsException() { - AccountHolder holder = new AccountHolder(); - } -} +package com.baeldung.stackoverflowerror; + +import org.junit.Test; + +public class AccountHolderManualTest { + @Test(expected = StackOverflowError.class) + public void whenInstanciatingAccountHolder_thenThrowsException() { + AccountHolder holder = new AccountHolder(); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java index 1f1de9149a..95164ac935 100644 --- a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/CyclicDependancyManualTest.java @@ -1,10 +1,10 @@ -package com.baeldung.stackoverflowerror; - -import org.junit.Test; - -public class CyclicDependancyManualTest { - @Test(expected = StackOverflowError.class) - public void whenInstanciatingClassOne_thenThrowsException() { - ClassOne obj = new ClassOne(); - } -} +package com.baeldung.stackoverflowerror; + +import org.junit.Test; + +public class CyclicDependancyManualTest { + @Test(expected = StackOverflowError.class) + public void whenInstanciatingClassOne_thenThrowsException() { + ClassOne obj = new ClassOne(); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java similarity index 97% rename from core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java index 3530fa1c3e..ccf8c25271 100644 --- a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/InfiniteRecursionWithTerminationConditionManualTest.java @@ -1,31 +1,31 @@ -package com.baeldung.stackoverflowerror; - -import org.junit.Test; - -import static junit.framework.TestCase.assertEquals; - -public class InfiniteRecursionWithTerminationConditionManualTest { - @Test - public void givenPositiveIntNoOne_whenCalcFact_thenCorrectlyCalc() { - int numToCalcFactorial = 1; - InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); - - assertEquals(1, irtc.calculateFactorial(numToCalcFactorial)); - } - - @Test - public void givenPositiveIntGtOne_whenCalcFact_thenCorrectlyCalc() { - int numToCalcFactorial = 5; - InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); - - assertEquals(120, irtc.calculateFactorial(numToCalcFactorial)); - } - - @Test(expected = StackOverflowError.class) - public void givenNegativeInt_whenCalcFact_thenThrowsException() { - int numToCalcFactorial = -1; - InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); - - irtc.calculateFactorial(numToCalcFactorial); - } -} +package com.baeldung.stackoverflowerror; + +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +public class InfiniteRecursionWithTerminationConditionManualTest { + @Test + public void givenPositiveIntNoOne_whenCalcFact_thenCorrectlyCalc() { + int numToCalcFactorial = 1; + InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); + + assertEquals(1, irtc.calculateFactorial(numToCalcFactorial)); + } + + @Test + public void givenPositiveIntGtOne_whenCalcFact_thenCorrectlyCalc() { + int numToCalcFactorial = 5; + InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); + + assertEquals(120, irtc.calculateFactorial(numToCalcFactorial)); + } + + @Test(expected = StackOverflowError.class) + public void givenNegativeInt_whenCalcFact_thenThrowsException() { + int numToCalcFactorial = -1; + InfiniteRecursionWithTerminationCondition irtc = new InfiniteRecursionWithTerminationCondition(); + + irtc.calculateFactorial(numToCalcFactorial); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java similarity index 96% rename from core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java index 858cec2ffa..40c2c4799e 100644 --- a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/RecursionWithCorrectTerminationConditionManualTest.java @@ -1,15 +1,15 @@ -package com.baeldung.stackoverflowerror; - -import org.junit.Test; - -import static junit.framework.TestCase.assertEquals; - -public class RecursionWithCorrectTerminationConditionManualTest { - @Test - public void givenNegativeInt_whenCalcFact_thenCorrectlyCalc() { - int numToCalcFactorial = -1; - RecursionWithCorrectTerminationCondition rctc = new RecursionWithCorrectTerminationCondition(); - - assertEquals(1, rctc.calculateFactorial(numToCalcFactorial)); - } -} +package com.baeldung.stackoverflowerror; + +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +public class RecursionWithCorrectTerminationConditionManualTest { + @Test + public void givenNegativeInt_whenCalcFact_thenCorrectlyCalc() { + int numToCalcFactorial = -1; + RecursionWithCorrectTerminationCondition rctc = new RecursionWithCorrectTerminationCondition(); + + assertEquals(1, rctc.calculateFactorial(numToCalcFactorial)); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java similarity index 97% rename from core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java index 1e1c245d4d..f4e2e5221a 100644 --- a/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/stackoverflowerror/UnintendedInfiniteRecursionManualTest.java @@ -1,30 +1,30 @@ -package com.baeldung.stackoverflowerror; - - -import org.junit.Test; - -public class UnintendedInfiniteRecursionManualTest { - @Test(expected = StackOverflowError.class) - public void givenPositiveIntNoOne_whenCalFact_thenThrowsException() { - int numToCalcFactorial = 1; - UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); - - uir.calculateFactorial(numToCalcFactorial); - } - - @Test(expected = StackOverflowError.class) - public void givenPositiveIntGtOne_whenCalcFact_thenThrowsException() { - int numToCalcFactorial = 2; - UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); - - uir.calculateFactorial(numToCalcFactorial); - } - - @Test(expected = StackOverflowError.class) - public void givenNegativeInt_whenCalcFact_thenThrowsException() { - int numToCalcFactorial = -1; - UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); - - uir.calculateFactorial(numToCalcFactorial); - } -} +package com.baeldung.stackoverflowerror; + + +import org.junit.Test; + +public class UnintendedInfiniteRecursionManualTest { + @Test(expected = StackOverflowError.class) + public void givenPositiveIntNoOne_whenCalFact_thenThrowsException() { + int numToCalcFactorial = 1; + UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); + + uir.calculateFactorial(numToCalcFactorial); + } + + @Test(expected = StackOverflowError.class) + public void givenPositiveIntGtOne_whenCalcFact_thenThrowsException() { + int numToCalcFactorial = 2; + UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); + + uir.calculateFactorial(numToCalcFactorial); + } + + @Test(expected = StackOverflowError.class) + public void givenNegativeInt_whenCalcFact_thenThrowsException() { + int numToCalcFactorial = -1; + UnintendedInfiniteRecursion uir = new UnintendedInfiniteRecursion(); + + uir.calculateFactorial(numToCalcFactorial); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/synthetic/SyntheticUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/synthetic/SyntheticUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/synthetic/SyntheticUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/synthetic/SyntheticUnitTest.java diff --git a/core-java-lang/src/test/java/com/baeldung/throwsexception/SimpleServiceUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/throwsexception/SimpleServiceUnitTest.java similarity index 100% rename from core-java-lang/src/test/java/com/baeldung/throwsexception/SimpleServiceUnitTest.java rename to core-java-modules/core-java-lang/src/test/java/com/baeldung/throwsexception/SimpleServiceUnitTest.java diff --git a/core-java-lang/src/test/resources/correctFileNameWithoutProperExtension b/core-java-modules/core-java-lang/src/test/resources/correctFileNameWithoutProperExtension similarity index 100% rename from core-java-lang/src/test/resources/correctFileNameWithoutProperExtension rename to core-java-modules/core-java-lang/src/test/resources/correctFileNameWithoutProperExtension diff --git a/core-java-modules/core-java-networking/.gitignore b/core-java-modules/core-java-networking/.gitignore new file mode 100644 index 0000000000..374c8bf907 --- /dev/null +++ b/core-java-modules/core-java-networking/.gitignore @@ -0,0 +1,25 @@ +*.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 +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml \ No newline at end of file diff --git a/core-java-modules/core-java-networking/README.md b/core-java-modules/core-java-networking/README.md new file mode 100644 index 0000000000..2341520df7 --- /dev/null +++ b/core-java-modules/core-java-networking/README.md @@ -0,0 +1,18 @@ +========= + +## Core Java Networking + +### Relevant Articles + +- [Connecting Through Proxy Servers in Core Java](https://www.baeldung.com/java-connect-via-proxy-server) +- [Broadcasting and Multicasting in Java](http://www.baeldung.com/java-broadcast-multicast) +- [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) +- [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) +- [Do 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) +- [Read an InputStream using the Java Server Socket](https://www.baeldung.com/java-inputstream-server-socket) diff --git a/core-java-modules/core-java-networking/pom.xml b/core-java-modules/core-java-networking/pom.xml new file mode 100644 index 0000000000..550ebdb4ff --- /dev/null +++ b/core-java-modules/core-java-networking/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + core-java-networking + 0.1.0-SNAPSHOT + core-java-networking + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + javax.mail + mail + ${javax.mail.version} + + + commons-io + commons-io + ${commons-io.version} + + + org.springframework + spring-web + ${springframework.spring-web.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + core-java-networking + + + + 1.5.0-b01 + 2.5 + 3.5 + 4.3.4.RELEASE + + diff --git a/core-java-modules/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java new file mode 100644 index 0000000000..394255bd70 --- /dev/null +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java @@ -0,0 +1,65 @@ +package com.baeldung.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.util.Iterator; +import java.util.List; + +public class FullResponseBuilder { + public static String getFullResponse(HttpURLConnection con) throws IOException { + StringBuilder fullResponseBuilder = new StringBuilder(); + + fullResponseBuilder.append(con.getResponseCode()) + .append(" ") + .append(con.getResponseMessage()) + .append("\n"); + + con.getHeaderFields() + .entrySet() + .stream() + .filter(entry -> entry.getKey() != null) + .forEach(entry -> { + + fullResponseBuilder.append(entry.getKey()) + .append(": "); + + List headerValues = entry.getValue(); + Iterator it = headerValues.iterator(); + if (it.hasNext()) { + fullResponseBuilder.append(it.next()); + + while (it.hasNext()) { + fullResponseBuilder.append(", ") + .append(it.next()); + } + } + + fullResponseBuilder.append("\n"); + }); + + Reader streamReader = null; + + if (con.getResponseCode() > 299) { + streamReader = new InputStreamReader(con.getErrorStream()); + } else { + streamReader = new InputStreamReader(con.getInputStream()); + } + + BufferedReader in = new BufferedReader(streamReader); + String inputLine; + StringBuilder content = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + + in.close(); + + fullResponseBuilder.append("Response: ") + .append(content); + + return fullResponseBuilder.toString(); + } +} diff --git a/core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/http/ParameterStringBuilder.java similarity index 100% rename from core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/http/ParameterStringBuilder.java diff --git a/core-java/src/main/java/com/baeldung/mail/EmailService.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/mail/EmailService.java similarity index 100% rename from core-java/src/main/java/com/baeldung/mail/EmailService.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/mail/EmailService.java diff --git a/core-java/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java diff --git a/core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java similarity index 87% rename from core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java index 0b5f6d7714..9fbbee8501 100644 --- a/core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java @@ -17,8 +17,8 @@ public class ProxyAcceptCookiePolicy implements CookiePolicy { host = uri.getHost(); } - if (!HttpCookie.domainMatches(acceptedProxy, host)) { - return false; + if (HttpCookie.domainMatches(acceptedProxy, host)) { + return true; } return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie); diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java diff --git a/core-java-networking/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java similarity index 100% rename from core-java-networking/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/EchoClient.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/EchoClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/EchoClient.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/EchoClient.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/EchoServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/EchoServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/EchoServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/EchoServer.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java diff --git a/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java diff --git a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java similarity index 98% rename from core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java index 121e0f5d72..91f6e21293 100644 --- a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java @@ -1,4 +1,4 @@ -package com.baeldung.javanetworking.uriurl; +package com.baeldung.networking.uriurl; import java.io.BufferedReader; import java.io.IOException; diff --git a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java similarity index 98% rename from core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java index 109a9951d2..d257e7a295 100644 --- a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java @@ -1,4 +1,4 @@ -package com.baeldung.javanetworking.uriurl; +package com.baeldung.networking.uriurl; import java.io.BufferedReader; import java.io.IOException; diff --git a/core-java/src/main/java/com/baeldung/socket/EchoClient.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/socket/EchoClient.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoClient.java diff --git a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoMultiServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoMultiServer.java diff --git a/core-java/src/main/java/com/baeldung/socket/EchoServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/socket/EchoServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/EchoServer.java diff --git a/core-java/src/main/java/com/baeldung/socket/GreetClient.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/GreetClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/socket/GreetClient.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/GreetClient.java diff --git a/core-java/src/main/java/com/baeldung/socket/GreetServer.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/GreetServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/socket/GreetServer.java rename to core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/GreetServer.java diff --git a/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java new file mode 100644 index 0000000000..5e2a84a767 --- /dev/null +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java @@ -0,0 +1,29 @@ +package com.baeldung.socket.read; + +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.io.*; + +public class Client { + + public void runClient(String ip, int port) { + try { + Socket socket = new Socket(ip, port); + System.out.println("Connected to server ..."); + 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) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java new file mode 100644 index 0000000000..2ab91c6cdc --- /dev/null +++ b/core-java-modules/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java @@ -0,0 +1,49 @@ +package com.baeldung.socket.read; + +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.io.*; + +public class Server { + + public void runServer(int port) { + //Start the server and wait for connection + try { + ServerSocket server = new ServerSocket(port); + System.out.println("Server Started. Waiting for connection ..."); + Socket socket = server.accept(); + System.out.println("Got connection from client."); + //Get input stream from socket variable and convert the same to DataInputStream + 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); + 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); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-networking/src/main/resources/logback.xml b/core-java-modules/core-java-networking/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-networking/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java similarity index 64% rename from core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java index acd6536ac4..bd6c0a4410 100644 --- a/core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java @@ -1,12 +1,13 @@ package com.baeldung.http; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.Test; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.io.Reader; import java.net.CookieManager; import java.net.HttpCookie; import java.net.HttpURLConnection; @@ -48,7 +49,8 @@ public class HttpRequestLiveTest { in.close(); assertEquals("status code incorrect", status, 200); - assertTrue("content incorrect", content.toString().contains("Example Domain")); + assertTrue("content incorrect", content.toString() + .contains("Example Domain")); } @Test @@ -89,18 +91,24 @@ public class HttpRequestLiveTest { Optional usernameCookie = null; if (cookiesHeader != null) { List cookies = HttpCookie.parse(cookiesHeader); - cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie)); - usernameCookie = cookies.stream().findAny().filter(cookie -> cookie.getName().equals("username")); + cookies.forEach(cookie -> cookieManager.getCookieStore() + .add(null, cookie)); + usernameCookie = cookies.stream() + .findAny() + .filter(cookie -> cookie.getName() + .equals("username")); } if (usernameCookie == null) { - cookieManager.getCookieStore().add(null, new HttpCookie("username", "john")); + cookieManager.getCookieStore() + .add(null, new HttpCookie("username", "john")); } con.disconnect(); con = (HttpURLConnection) url.openConnection(); - con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";")); + con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore() + .getCookies(), ";")); int status = con.getResponseCode(); @@ -125,4 +133,56 @@ public class HttpRequestLiveTest { assertEquals("status code incorrect", con.getResponseCode(), 200); } + @Test + public void whenFailedRequest_thenOk() throws IOException { + URL url = new URL("http://example.com"); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + + con.setConnectTimeout(5000); + con.setReadTimeout(5000); + + int status = con.getResponseCode(); + + Reader streamReader = null; + + if (status > 299) { + streamReader = new InputStreamReader(con.getErrorStream()); + } else { + streamReader = new InputStreamReader(con.getInputStream()); + } + + BufferedReader in = new BufferedReader(streamReader); + String inputLine; + StringBuilder content = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + + con.disconnect(); + + assertEquals("status code incorrect", status, 411); + assertTrue("error content", content.toString() + .contains("411 - Length Required")); + } + + @Test + public void whenGetRequestFullResponse_thenOk() throws IOException { + URL url = new URL("http://example.com"); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + con.setConnectTimeout(5000); + con.setReadTimeout(5000); + + String fullResponse = FullResponseBuilder.getFullResponse(con); + + con.disconnect(); + + assertEquals("status code incorrect", con.getResponseCode(), 200); + assertTrue("header incorrect", fullResponse.contains("Content-Type: text/html; charset=UTF-8")); + assertTrue("response incorrect", fullResponse.contains("")); + } + } diff --git a/core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java index 8635a24f18..47a598f599 100644 --- a/core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.interfaces; +package com.baeldung.networking.interfaces; import org.junit.Test; diff --git a/core-java/src/test/java/com/baeldung/networking/udp/UDPLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/UDPLiveTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/networking/udp/UDPLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/UDPLiveTest.java diff --git a/core-java/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastLiveTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastLiveTest.java diff --git a/core-java/src/test/java/com/baeldung/networking/udp/multicast/MulticastLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/multicast/MulticastLiveTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/networking/udp/multicast/MulticastLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/udp/multicast/MulticastLiveTest.java diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java similarity index 95% rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java index 0c312ff613..3b73cc0943 100644 --- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.javanetworking.uriurl.test; +package com.baeldung.networking.uriurl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -20,7 +20,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.baeldung.javanetworking.uriurl.URLDemo; +import com.baeldung.networking.uriurl.URLDemo; @FixMethodOrder public class URIDemoLiveTest { diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java index 8837dc5556..ec1cb4c0c9 100644 --- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.javanetworking.uriurl; +package com.baeldung.networking.uriurl; import java.io.IOException; import java.net.MalformedURLException; diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java index 15f53ed878..a9104311e6 100644 --- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.javanetworking.uriurl.test; +package com.baeldung.networking.uriurl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -18,7 +18,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.baeldung.javanetworking.uriurl.URLDemo; +import com.baeldung.networking.uriurl.URLDemo; @FixMethodOrder public class URLDemoLiveTest { diff --git a/core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java index 505d9595ab..112f2cf53f 100644 --- a/core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java +++ b/core-java-modules/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.url; +package com.baeldung.networking.url; import static org.junit.Assert.assertEquals; diff --git a/core-java/src/test/java/com/baeldung/socket/EchoIntegrationTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/EchoIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/socket/EchoIntegrationTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/EchoIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java rename to core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java diff --git a/core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java b/core-java-modules/core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java new file mode 100644 index 0000000000..da7f5b8d3f --- /dev/null +++ b/core-java-modules/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 diff --git a/core-java-sun/src/test/resources/.gitignore b/core-java-modules/core-java-networking/src/test/resources/.gitignore similarity index 100% rename from core-java-sun/src/test/resources/.gitignore rename to core-java-modules/core-java-networking/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-nio/.gitignore b/core-java-modules/core-java-nio/.gitignore new file mode 100644 index 0000000000..c61d35324d --- /dev/null +++ b/core-java-modules/core-java-nio/.gitignore @@ -0,0 +1,5 @@ +0.* + +# Files generated by integration tests +# *.txt +/temp \ No newline at end of file diff --git a/core-java-modules/core-java-nio/README.md b/core-java-modules/core-java-nio/README.md new file mode 100644 index 0000000000..9034c3b3b1 --- /dev/null +++ b/core-java-modules/core-java-nio/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Determine File Creating Date in Java](https://www.baeldung.com/java-file-creation-date) diff --git a/core-java-modules/core-java-nio/pom.xml b/core-java-modules/core-java-nio/pom.xml new file mode 100644 index 0000000000..31433e632f --- /dev/null +++ b/core-java-modules/core-java-nio/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + core-java-nio + 0.1.0-SNAPSHOT + core-java-nio + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + \ No newline at end of file diff --git a/core-java-modules/core-java-nio/src/main/java/com/baeldung/creationdate/CreationDateResolver.java b/core-java-modules/core-java-nio/src/main/java/com/baeldung/creationdate/CreationDateResolver.java new file mode 100644 index 0000000000..6347a6e681 --- /dev/null +++ b/core-java-modules/core-java-nio/src/main/java/com/baeldung/creationdate/CreationDateResolver.java @@ -0,0 +1,35 @@ +package com.baeldung.creationdate; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.time.Instant; +import java.util.Optional; + +public class CreationDateResolver { + + public Instant resolveCreationTimeWithBasicAttributes(Path path) { + try { + final BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class); + final FileTime fileTime = attr.creationTime(); + + return fileTime.toInstant(); + } catch (IOException ex) { + throw new RuntimeException("An issue occured went wrong when resolving creation time", ex); + } + } + + public Optional resolveCreationTimeWithAttribute(Path path) { + try { + final FileTime creationTime = (FileTime) Files.getAttribute(path, "creationTime"); + + return Optional + .ofNullable(creationTime) + .map((FileTime::toInstant)); + } catch (IOException ex) { + throw new RuntimeException("An issue occured went wrong when resolving creation time", ex); + } + } +} diff --git a/core-java-modules/core-java-nio/src/test/java/com/baeldung/creationdate/CreationDateResolverUnitTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/creationdate/CreationDateResolverUnitTest.java new file mode 100644 index 0000000000..5402852c74 --- /dev/null +++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/creationdate/CreationDateResolverUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.creationdate; + +import org.junit.Test; + +import java.io.File; +import java.nio.file.Path; +import java.time.Instant; +import java.util.Optional; + +import static org.junit.Assert.assertTrue; + +public class CreationDateResolverUnitTest { + + private final CreationDateResolver creationDateResolver = new CreationDateResolver(); + + @Test + public void givenFile_whenGettingCreationDateTimeFromBasicAttributes_thenReturnDate() throws Exception { + + final File file = File.createTempFile("createdFile", ".txt"); + final Path path = file.toPath(); + + final Instant response = creationDateResolver.resolveCreationTimeWithBasicAttributes(path); + + assertTrue(Instant + .now() + .isAfter(response)); + + } + + @Test + public void givenFile_whenGettingCreationDateTimeFromAttribute_thenReturnDate() throws Exception { + + final File file = File.createTempFile("createdFile", ".txt"); + final Path path = file.toPath(); + + final Optional response = creationDateResolver.resolveCreationTimeWithAttribute(path); + + response.ifPresent((value) -> { + assertTrue(Instant + .now() + .isAfter(value)); + }); + + } +} diff --git a/core-java-modules/core-java-nio/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java b/core-java-modules/core-java-nio/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java new file mode 100644 index 0000000000..d661b8f7fb --- /dev/null +++ b/core-java-modules/core-java-nio/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java @@ -0,0 +1,165 @@ +package com.baeldung.filechannel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +public class FileChannelUnitTest { + + @Test + public void givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel(); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + + assertEquals("Hello world", fileContent); + } + } + + @Test + public void givenFile_whenReadWithFileChannelUsingFileInputStream_thenCorrect() throws IOException { + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); + FileInputStream fin = new FileInputStream("src/test/resources/test_read.in"); + FileChannel channel = fin.getChannel()) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + + assertEquals("Hello world", fileContent); + } + } + + @Test + public void givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel(); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + + MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 6, 5); + + if (buff.hasRemaining()) { + byte[] data = new byte[buff.remaining()]; + buff.get(data); + assertEquals("world", new String(data, StandardCharsets.UTF_8)); + } + } + } + + @Test + public void whenWriteWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException { + String file = "src/test/resources/test_write_using_filechannel.txt"; + try (RandomAccessFile writer = new RandomAccessFile(file, "rw"); + FileChannel channel = writer.getChannel()) { + ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8)); + + channel.write(buff); + + // now we verify whether the file was written correctly + RandomAccessFile reader = new RandomAccessFile(file, "r"); + assertEquals("Hello world", reader.readLine()); + reader.close(); + } + } + + @Test + public void givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect() throws IOException { + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "rw"); + FileChannel channel = reader.getChannel(); + FileLock fileLock = channel.tryLock(6, 5, Boolean.FALSE);) { + + assertNotNull(fileLock); + } + } + + @Test + public void givenFile_whenReadWithFileChannelGetPosition_thenCorrect() throws IOException { + + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); + RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel()) { + + int bufferSize = 1024; + if (bufferSize > channel.size()) { + bufferSize = (int) channel.size(); + } + ByteBuffer buff = ByteBuffer.allocate(bufferSize); + + while (channel.read(buff) > 0) { + out.write(buff.array(), 0, buff.position()); + buff.clear(); + } + + // the original file is 11 bytes long, so that's where the position pointer should be + assertEquals(11, channel.position()); + + channel.position(4); + assertEquals(4, channel.position()); + } + } + + @Test + public void whenGetFileSize_thenCorrect() throws IOException { + + try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r"); + FileChannel channel = reader.getChannel()) { + + // the original file is 11 bytes long, so that's where the position pointer should be + assertEquals(11, channel.size()); + } + } + + @Test + public void whenTruncateFile_thenCorrect() throws IOException { + String input = "this is a test input"; + + FileOutputStream fout = new FileOutputStream("src/test/resources/test_truncate.txt"); + FileChannel channel = fout.getChannel(); + + ByteBuffer buff = ByteBuffer.wrap(input.getBytes()); + channel.write(buff); + buff.flip(); + + channel = channel.truncate(5); + assertEquals(5, channel.size()); + + fout.close(); + channel.close(); + } +} diff --git a/core-java/src/main/java/com/baeldung/.gitignore b/core-java-modules/core-java-nio/src/test/resources/.gitignore similarity index 100% rename from core-java/src/main/java/com/baeldung/.gitignore rename to core-java-modules/core-java-nio/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-nio/src/test/resources/test_read.in b/core-java-modules/core-java-nio/src/test/resources/test_read.in new file mode 100644 index 0000000000..70c379b63f --- /dev/null +++ b/core-java-modules/core-java-nio/src/test/resources/test_read.in @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/core-java-modules/core-java-nio/src/test/resources/test_truncate.txt b/core-java-modules/core-java-nio/src/test/resources/test_truncate.txt new file mode 100644 index 0000000000..26d3b38cdd --- /dev/null +++ b/core-java-modules/core-java-nio/src/test/resources/test_truncate.txt @@ -0,0 +1 @@ +this \ No newline at end of file diff --git a/core-java-modules/core-java-nio/src/test/resources/test_write_using_filechannel.txt b/core-java-modules/core-java-nio/src/test/resources/test_write_using_filechannel.txt new file mode 100644 index 0000000000..70c379b63f --- /dev/null +++ b/core-java-modules/core-java-nio/src/test/resources/test_write_using_filechannel.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/core-java-modules/core-java-optional/README.md b/core-java-modules/core-java-optional/README.md new file mode 100644 index 0000000000..b6848b5d33 --- /dev/null +++ b/core-java-modules/core-java-optional/README.md @@ -0,0 +1,6 @@ +========= + +## Core Java Optional + +### Relevant Articles: +- [Java Optional as Return Type](https://www.baeldung.com/java-optional-return) diff --git a/core-java-modules/core-java-optional/pom.xml b/core-java-modules/core-java-optional/pom.xml new file mode 100644 index 0000000000..f60e3ba03d --- /dev/null +++ b/core-java-modules/core-java-optional/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + core-java-optional + 0.1.0-SNAPSHOT + jar + + + com.baeldung.core-java-modules + core-java-modules + 1.0.0-SNAPSHOT + + + + + org.hibernate + hibernate-core + ${hibernate.core.version} + + + com.h2database + h2 + ${h2database.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.databind.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + UTF-8 + 1.8 + 1.8 + 5.4.0.Final + 1.4.197 + 2.9.8 + + \ No newline at end of file diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/HandleOptionalTypeExample.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/HandleOptionalTypeExample.java new file mode 100644 index 0000000000..c472bab077 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/HandleOptionalTypeExample.java @@ -0,0 +1,41 @@ +package com.baeldung.optionalReturnType; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class HandleOptionalTypeExample { + static Map usersByName = new HashMap(); + static { + User user1 = new User(); + user1.setUserId(1l); + user1.setFirstName("baeldung"); + usersByName.put("baeldung", user1); + } + + public static void main(String[] args) { + changeUserName("baeldung", "baeldung-new"); + changeUserName("user", "user-new"); + } + + public static void changeUserName(String oldFirstName, String newFirstName) { + Optional userOpt = findUserByName(oldFirstName); + if (userOpt.isPresent()) { + User user = userOpt.get(); + user.setFirstName(newFirstName); + + System.out.println("user with name " + oldFirstName + " is changed to " + user.getFirstName()); + } else { + // user is missing + System.out.println("user with name " + oldFirstName + " is not found."); + } + } + + public static Optional findUserByName(String name) { + // look up the user in the database, the user object below could be null + User user = usersByName.get(name); + Optional opt = Optional.ofNullable(user); + + return opt; + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/OptionalToJsonExample.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/OptionalToJsonExample.java new file mode 100644 index 0000000000..b44a35fae1 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/OptionalToJsonExample.java @@ -0,0 +1,19 @@ +package com.baeldung.optionalReturnType; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class OptionalToJsonExample { + public static void main(String[] args) { + UserOptional user = new UserOptional(); + user.setUserId(1l); + user.setFirstName("Bael Dung"); + + ObjectMapper om = new ObjectMapper(); + try { + System.out.print("user in json is:" + om.writeValueAsString(user)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample.java new file mode 100644 index 0000000000..85c96b9bc3 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample.java @@ -0,0 +1,26 @@ +package com.baeldung.optionalReturnType; + +import java.util.Optional; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class PersistOptionalTypeExample { + static String persistenceUnit = "com.baeldung.optionalReturnType"; + static EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit); + + static EntityManager entityManager = emf.createEntityManager(); + + // to run this app, uncomment the follow line in META-INF/persistence.xml + // com.baeldung.optionalReturnType.UserOptionalField + public static void main(String[] args) { + UserOptionalField user1 = new UserOptionalField(); + user1.setUserId(1l); + user1.setFirstName(Optional.of("Bael Dung")); + entityManager.persist(user1); + + UserOptional user2 = entityManager.find(UserOptional.class, 1l); + System.out.print("User2.firstName:" + user2.getFirstName()); + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample2.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample2.java new file mode 100644 index 0000000000..3114e7cefb --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistOptionalTypeExample2.java @@ -0,0 +1,22 @@ +package com.baeldung.optionalReturnType; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class PersistOptionalTypeExample2 { + static String persistenceUnit = "com.baeldung.optionalReturnType"; + static EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit); + + static EntityManager em = emf.createEntityManager(); + + public static void main(String[] args) { + UserOptional user1 = new UserOptional(); + user1.setUserId(1l); + user1.setFirstName("Bael Dung"); + em.persist(user1); + + UserOptional user2 = em.find(UserOptional.class, 1l); + System.out.print("User2.firstName:" + user2.getFirstName()); + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistUserExample.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistUserExample.java new file mode 100644 index 0000000000..f1284958e7 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/PersistUserExample.java @@ -0,0 +1,22 @@ +package com.baeldung.optionalReturnType; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class PersistUserExample { + static String persistenceUnit = "com.baeldung.optionalReturnType"; + static EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit); + + static EntityManager em = emf.createEntityManager(); + + public static void main(String[] args) { + User user1 = new User(); + user1.setUserId(1l); + user1.setFirstName("Bael Dung"); + em.persist(user1); + + User user2 = em.find(User.class, 1l); + System.out.print("User2.firstName:" + user2.getFirstName()); + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/SerializeOptionalTypeExample.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/SerializeOptionalTypeExample.java new file mode 100644 index 0000000000..d67337ad98 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/SerializeOptionalTypeExample.java @@ -0,0 +1,41 @@ +package com.baeldung.optionalReturnType; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.Optional; + +public class SerializeOptionalTypeExample { + public static void main(String[] args) { + User user1 = new User(); + user1.setUserId(1l); + user1.setFirstName("baeldung"); + + serializeObject(user1, "user1.ser"); + + UserOptionalField user2 = new UserOptionalField(); + user2.setUserId(1l); + user2.setFirstName(Optional.of("baeldung")); + + serializeObject(user2, "user2.ser"); + + } + + public static void serializeObject(Object object, String fileName) { + // Serialization + try { + FileOutputStream file = new FileOutputStream(fileName); + ObjectOutputStream out = new ObjectOutputStream(file); + + out.writeObject(object); + + out.close(); + file.close(); + + System.out.println("Object " + object.toString() + " has been serialized to file " + fileName); + + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/User.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/User.java new file mode 100644 index 0000000000..7aa11d78cb --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/User.java @@ -0,0 +1,31 @@ +package com.baeldung.optionalReturnType; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class User implements Serializable { + @Id + private long userId; + + private String firstName; + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptional.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptional.java new file mode 100644 index 0000000000..0138a84ab9 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptional.java @@ -0,0 +1,35 @@ +package com.baeldung.optionalReturnType; + +import java.io.Serializable; +import java.util.Optional; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class UserOptional implements Serializable { + @Id + private long userId; + + @Column(nullable = true) + private String firstName; + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public Optional getFirstName() { + return Optional.ofNullable(firstName); + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + Optional.ofNullable(firstName); + } + +} diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptionalField.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptionalField.java new file mode 100644 index 0000000000..c02430b1ba --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/optionalReturnType/UserOptionalField.java @@ -0,0 +1,31 @@ +package com.baeldung.optionalReturnType; + +import java.io.Serializable; +import java.util.Optional; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class UserOptionalField implements Serializable { + @Id + private long userId; + + private Optional firstName; + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public Optional getFirstName() { + return firstName; + } + + public void setFirstName(Optional firstName) { + this.firstName = firstName; + } +} diff --git a/core-java-modules/core-java-os/.gitignore b/core-java-modules/core-java-os/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/core-java-modules/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-modules/core-java-os/README.md b/core-java-modules/core-java-os/README.md new file mode 100644 index 0000000000..5f5d373d9b --- /dev/null +++ b/core-java-modules/core-java-os/README.md @@ -0,0 +1,10 @@ +========= + +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) + diff --git a/core-java-modules/core-java-os/pom.xml b/core-java-modules/core-java-os/pom.xml new file mode 100644 index 0000000000..85194b176e --- /dev/null +++ b/core-java-modules/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-modules/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-modules/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-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java similarity index 96% rename from core-java-9/src/main/java/com/baeldung/java9/process/OutputStreamExample.java rename to core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java index 443847916a..37378f9d6c 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/process/OutputStreamExample.java +++ b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java @@ -1,16 +1,16 @@ -package com.baeldung.java9.process; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public class OutputStreamExample { - - public static void main(String[] args) { - Logger log = Logger.getLogger(OutputStreamExample.class.getName()); - log.log(Level.INFO, Integer.toString(sum(1,2))); - } - - public static int sum(int a, int b) { - return a + b; - } -} +package com.baeldung.java9.process; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class OutputStreamExample { + + public static void main(String[] args) { + Logger log = Logger.getLogger(OutputStreamExample.class.getName()); + log.log(Level.INFO, Integer.toString(sum(1,2))); + } + + public static int sum(int a, int b) { + return a + b; + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java b/core-java-modules/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-modules/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-modules/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-modules/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-modules/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-modules/core-java-os/src/main/java/com/baeldung/java9/process/ProcessUtils.java similarity index 96% rename from core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java rename to core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/ProcessUtils.java index 5cd2567fb3..1b952f0c3c 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java +++ b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/ProcessUtils.java @@ -1,43 +1,43 @@ -package com.baeldung.java9.process; - -import java.io.File; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.time.Duration; -import java.time.Instant; -import java.util.stream.Stream; - -public class ProcessUtils { - - public static String getClassPath() { - String cp = System.getProperty("java.class.path"); - System.out.println("ClassPath is " + cp); - return cp; - } - - public static File getJavaCmd() throws IOException { - String javaHome = System.getProperty("java.home"); - File javaCmd; - if (System.getProperty("os.name").startsWith("Win")) { - javaCmd = new File(javaHome, "bin/java.exe"); - } else { - javaCmd = new File(javaHome, "bin/java"); - } - if (javaCmd.canExecute()) { - return javaCmd; - } else { - throw new UnsupportedOperationException(javaCmd.getCanonicalPath() + " is not executable"); - } - } - - public static String getMainClass() { - return System.getProperty("sun.java.command"); - } - - public static String getSystemProperties() { - StringBuilder sb = new StringBuilder(); - System.getProperties().forEach((s1, s2) -> sb.append(s1 + " - " + s2)); - return sb.toString(); - } -} +package com.baeldung.java9.process; + +import java.io.File; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.time.Duration; +import java.time.Instant; +import java.util.stream.Stream; + +public class ProcessUtils { + + public static String getClassPath() { + String cp = System.getProperty("java.class.path"); + System.out.println("ClassPath is " + cp); + return cp; + } + + public static File getJavaCmd() throws IOException { + String javaHome = System.getProperty("java.home"); + File javaCmd; + if (System.getProperty("os.name").startsWith("Win")) { + javaCmd = new File(javaHome, "bin/java.exe"); + } else { + javaCmd = new File(javaHome, "bin/java"); + } + if (javaCmd.canExecute()) { + return javaCmd; + } else { + throw new UnsupportedOperationException(javaCmd.getCanonicalPath() + " is not executable"); + } + } + + public static String getMainClass() { + return System.getProperty("sun.java.command"); + } + + public static String getSystemProperties() { + StringBuilder sb = new StringBuilder(); + System.getProperties().forEach((s1, s2) -> sb.append(s1 + " - " + s2)); + return sb.toString(); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/ServiceMain.java similarity index 96% rename from core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java rename to core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/ServiceMain.java index 5dc00dba25..77831f601c 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java +++ b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/ServiceMain.java @@ -1,21 +1,21 @@ -package com.baeldung.java9.process; - -import java.util.Optional; - -public class ServiceMain { - - public static void main(String[] args) throws InterruptedException { - ProcessHandle thisProcess = ProcessHandle.current(); - long pid = thisProcess.pid(); - - Optional opArgs = Optional.ofNullable(args); - String procName = opArgs.map(str -> str.length > 0 ? str[0] : null).orElse(System.getProperty("sun.java.command")); - - for (int i = 0; i < 10000; i++) { - System.out.println("Process " + procName + " with ID " + pid + " is running!"); - Thread.sleep(10000); - } - - } - -} +package com.baeldung.java9.process; + +import java.util.Optional; + +public class ServiceMain { + + public static void main(String[] args) throws InterruptedException { + ProcessHandle thisProcess = ProcessHandle.current(); + long pid = thisProcess.pid(); + + Optional opArgs = Optional.ofNullable(args); + String procName = opArgs.map(str -> str.length > 0 ? str[0] : null).orElse(System.getProperty("sun.java.command")); + + for (int i = 0; i < 10000; i++) { + System.out.println("Process " + procName + " with ID " + pid + " is running!"); + Thread.sleep(10000); + } + + } + +} diff --git a/core-java-modules/core-java-os/src/main/resources/logback.xml b/core-java-modules/core-java-os/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/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-modules/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-modules/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-modules/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-modules/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-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java index e125f10da7..c3f390d8ae 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java @@ -1,111 +1,111 @@ -package com.baeldung.java9.process; - -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; - -import org.junit.Before; -import org.junit.Test; - -import junit.framework.Assert; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class ProcessApiUnitTest { - - @Before - public void init() { - - } - - @Test - public void processInfoExample() throws NoSuchAlgorithmException { - ProcessHandle self = ProcessHandle.current(); - long PID = self.getPid(); - ProcessHandle.Info procInfo = self.info(); - Optional args = procInfo.arguments(); - Optional cmd = procInfo.commandLine(); - Optional startTime = procInfo.startInstant(); - Optional cpuUsage = procInfo.totalCpuDuration(); - - waistCPU(); - System.out.println("Args " + args); - System.out.println("Command " + cmd.orElse("EmptyCmd")); - System.out.println("Start time: " + startTime.get().toString()); - System.out.println(cpuUsage.get().toMillis()); - - Stream allProc = ProcessHandle.current().children(); - allProc.forEach(p -> { - System.out.println("Proc " + p.getPid()); - }); - - } - - @Test - public void createAndDestroyProcess() throws IOException, InterruptedException { - int numberOfChildProcesses = 5; - for (int i = 0; i < numberOfChildProcesses; i++) { - createNewJVM(ServiceMain.class, i).getPid(); - } - - Stream childProc = ProcessHandle.current().children(); - assertEquals(childProc.count(), numberOfChildProcesses); - - childProc = ProcessHandle.current().children(); - childProc.forEach(processHandle -> { - assertTrue("Process " + processHandle.getPid() + " should be alive!", processHandle.isAlive()); - CompletableFuture onProcExit = processHandle.onExit(); - onProcExit.thenAccept(procHandle -> { - System.out.println("Process with PID " + procHandle.getPid() + " has stopped"); - }); - }); - - Thread.sleep(10000); - - childProc = ProcessHandle.current().children(); - childProc.forEach(procHandle -> { - assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy()); - }); - - Thread.sleep(5000); - - childProc = ProcessHandle.current().children(); - childProc.forEach(procHandle -> { - assertFalse("Process " + procHandle.getPid() + " should not be alive!", procHandle.isAlive()); - }); - - } - - private Process createNewJVM(Class mainClass, int number) throws IOException { - ArrayList cmdParams = new ArrayList(5); - cmdParams.add(ProcessUtils.getJavaCmd().getAbsolutePath()); - cmdParams.add("-cp"); - cmdParams.add(ProcessUtils.getClassPath()); - cmdParams.add(mainClass.getName()); - cmdParams.add("Service " + number); - ProcessBuilder myService = new ProcessBuilder(cmdParams); - myService.inheritIO(); - return myService.start(); - } - - private void waistCPU() throws NoSuchAlgorithmException { - ArrayList randArr = new ArrayList(4096); - SecureRandom sr = SecureRandom.getInstanceStrong(); - Duration somecpu = Duration.ofMillis(4200L); - Instant end = Instant.now().plus(somecpu); - while (Instant.now().isBefore(end)) { - // System.out.println(sr.nextInt()); - randArr.add(sr.nextInt()); - } - } - -} +package com.baeldung.java9.process; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; + +import junit.framework.Assert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ProcessApiUnitTest { + + @Before + public void init() { + + } + + @Test + public void processInfoExample() throws NoSuchAlgorithmException { + ProcessHandle self = ProcessHandle.current(); + long PID = self.pid(); + ProcessHandle.Info procInfo = self.info(); + Optional args = procInfo.arguments(); + Optional cmd = procInfo.commandLine(); + Optional startTime = procInfo.startInstant(); + Optional cpuUsage = procInfo.totalCpuDuration(); + + waistCPU(); + System.out.println("Args " + args); + System.out.println("Command " + cmd.orElse("EmptyCmd")); + System.out.println("Start time: " + startTime.get().toString()); + System.out.println(cpuUsage.get().toMillis()); + + Stream allProc = ProcessHandle.current().children(); + allProc.forEach(p -> { + System.out.println("Proc " + p.pid()); + }); + + } + + @Test + public void createAndDestroyProcess() throws IOException, InterruptedException { + int numberOfChildProcesses = 5; + for (int i = 0; i < numberOfChildProcesses; i++) { + createNewJVM(ServiceMain.class, i).pid(); + } + + Stream childProc = ProcessHandle.current().children(); + assertEquals(childProc.count(), numberOfChildProcesses); + + childProc = ProcessHandle.current().children(); + childProc.forEach(processHandle -> { + assertTrue("Process " + processHandle.pid() + " should be alive!", processHandle.isAlive()); + CompletableFuture onProcExit = processHandle.onExit(); + onProcExit.thenAccept(procHandle -> { + System.out.println("Process with PID " + procHandle.pid() + " has stopped"); + }); + }); + + Thread.sleep(10000); + + childProc = ProcessHandle.current().children(); + childProc.forEach(procHandle -> { + assertTrue("Could not kill process " + procHandle.pid(), procHandle.destroy()); + }); + + Thread.sleep(5000); + + childProc = ProcessHandle.current().children(); + childProc.forEach(procHandle -> { + assertFalse("Process " + procHandle.pid() + " should not be alive!", procHandle.isAlive()); + }); + + } + + private Process createNewJVM(Class mainClass, int number) throws IOException { + ArrayList cmdParams = new ArrayList(5); + cmdParams.add(ProcessUtils.getJavaCmd().getAbsolutePath()); + cmdParams.add("-cp"); + cmdParams.add(ProcessUtils.getClassPath()); + cmdParams.add(mainClass.getName()); + cmdParams.add("Service " + number); + ProcessBuilder myService = new ProcessBuilder(cmdParams); + myService.inheritIO(); + return myService.start(); + } + + private void waistCPU() throws NoSuchAlgorithmException { + ArrayList randArr = new ArrayList(4096); + SecureRandom sr = SecureRandom.getInstanceStrong(); + Duration somecpu = Duration.ofMillis(4200L); + Instant end = Instant.now().plus(somecpu); + while (Instant.now().isBefore(end)) { + // System.out.println(sr.nextInt()); + randArr.add(sr.nextInt()); + } + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessUnderstandingTest.java b/core-java-modules/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-modules/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-modules/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-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java new file mode 100644 index 0000000000..8fc5f9f160 --- /dev/null +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -0,0 +1,182 @@ +package com.baeldung.processbuilder; + +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); + } + + @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 { + 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 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()); + } + } + + 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"); + } + +} diff --git a/core-java/src/test/resources/.gitignore b/core-java-modules/core-java-os/src/test/resources/.gitignore similarity index 100% rename from core-java/src/test/resources/.gitignore rename to core-java-modules/core-java-os/src/test/resources/.gitignore diff --git a/core-java-modules/core-java-perf/README.md b/core-java-modules/core-java-perf/README.md new file mode 100644 index 0000000000..1b3b590bf8 --- /dev/null +++ b/core-java-modules/core-java-perf/README.md @@ -0,0 +1,9 @@ +## Core Java Performance + +### Relevant Articles: +- [Verbose Garbage Collection in Java](https://www.baeldung.com/java-verbose-gc) +- [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture) +- [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks) +- [OutOfMemoryError: GC Overhead Limit Exceeded](http://www.baeldung.com/java-gc-overhead-limit-exceeded) +- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) +- [Monitoring Java Applications with Flight Recorder](https://www.baeldung.com/java-flight-recorder-monitoring) diff --git a/core-java-modules/core-java-perf/pom.xml b/core-java-modules/core-java-perf/pom.xml new file mode 100644 index 0000000000..f225a9554b --- /dev/null +++ b/core-java-modules/core-java-perf/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + com.baeldung + core-java-perf + 0.1.0-SNAPSHOT + core-java-perf + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + + + 3.8.1 + + + + diff --git a/core-java-modules/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java new file mode 100644 index 0000000000..02c3e96124 --- /dev/null +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java @@ -0,0 +1,32 @@ +package com.baeldung.flightrecorder; + +import java.util.ArrayList; +import java.util.List; + +/** + * Simple program that illustrates how to use Java Flight Recorder. + * + * This programs creates a list, inserts objects in it until + * an OutOfMemoryError is thrown. + * + */ +public class FlightRecorder { + + public static void main(String[] args) { + List items = new ArrayList<>(1); + try { + while (true) { + items.add(new Object()); + } + } catch (OutOfMemoryError e) { + System.out.println(e.getMessage()); + } + assert items.size() > 0; + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } + +} diff --git a/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java similarity index 97% rename from core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java index f57580bbb5..9e4e6d9902 100644 --- a/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java @@ -1,63 +1,63 @@ -package com.baeldung.gc; - -import java.util.HashMap; -import java.util.Map; - -/** - * A simple Java program to demonstrate how to enable verbose Garbage Collection (GC) logging. - *

- * This simple program loads 3 million {@link java.lang.String} instances into a {@link java.util.HashMap} - * object before making an explicit call to the garbage collector using System.gc(). - *

- * Finally, it removes 2 million of the {@link java.lang.String} instances from the {@link java.util.HashMap}. - * We also explicitly use System.out.println to make interpreting the output easier. - *

- * Run this program with the following arguments to see verbose GC logging in its complete form: - *

- * -XX:+UseSerialGC -Xms1024m -Xmx1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/path/to/file/gc.log
- * 
- * Where: - *
    - *
  • -XX:+UseSerialGC - specify the serial garbage collector.
  • - *
  • -Xms1024m - specify the minimal heap size.
  • - *
  • -Xmx1024m - specify the maximal heap size.
  • - *
  • -verbose:gc - activate the logging of garbage collection information in its simplest form.
  • - *
  • -XX:+PrintGCDetails - activate detailed information about garbage collection.
  • - *
  • -XX:+PrintGCTimeStamps - include a timestamp in the output reflecting the real-time passed in seconds since the JVM started.
  • - *
  • -XX:+PrintGCDateStamps - include the absolute date and time at the start of each line.
  • - *
  • -Xloggc - by default the GC log is written to stdout. Specify an output file via this argument.
  • - *
- *

- * It should be noted that the first three arguments are not strictly necessary but for the purposes or the example - * help really simplify things. - * - */ -public class VerboseGarbageCollectorRunner { - - private static Map stringContainer = new HashMap<>(); - - public static void main(String[] args) { - System.out.println("Start of program!"); - String stringWithPrefix = "stringWithPrefix"; - - // Load Java Heap with 3 M java.lang.String instances - for (int i = 0; i < 3000000; i++) { - String newString = stringWithPrefix + i; - stringContainer.put(newString, newString); - } - System.out.println("MAP size: " + stringContainer.size()); - - // Explicit GC! - System.gc(); - - // Remove 2 M out of 3 M - for (int i = 0; i < 2000000; i++) { - String newString = stringWithPrefix + i; - stringContainer.remove(newString); - } - - System.out.println("MAP size: " + stringContainer.size()); - System.out.println("End of program!"); - } - -} +package com.baeldung.gc; + +import java.util.HashMap; +import java.util.Map; + +/** + * A simple Java program to demonstrate how to enable verbose Garbage Collection (GC) logging. + *

+ * This simple program loads 3 million {@link java.lang.String} instances into a {@link java.util.HashMap} + * object before making an explicit call to the garbage collector using System.gc(). + *

+ * Finally, it removes 2 million of the {@link java.lang.String} instances from the {@link java.util.HashMap}. + * We also explicitly use System.out.println to make interpreting the output easier. + *

+ * Run this program with the following arguments to see verbose GC logging in its complete form: + *

+ * -XX:+UseSerialGC -Xms1024m -Xmx1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/path/to/file/gc.log
+ * 
+ * Where: + *
    + *
  • -XX:+UseSerialGC - specify the serial garbage collector.
  • + *
  • -Xms1024m - specify the minimal heap size.
  • + *
  • -Xmx1024m - specify the maximal heap size.
  • + *
  • -verbose:gc - activate the logging of garbage collection information in its simplest form.
  • + *
  • -XX:+PrintGCDetails - activate detailed information about garbage collection.
  • + *
  • -XX:+PrintGCTimeStamps - include a timestamp in the output reflecting the real-time passed in seconds since the JVM started.
  • + *
  • -XX:+PrintGCDateStamps - include the absolute date and time at the start of each line.
  • + *
  • -Xloggc - by default the GC log is written to stdout. Specify an output file via this argument.
  • + *
+ *

+ * It should be noted that the first three arguments are not strictly necessary but for the purposes or the example + * help really simplify things. + * + */ +public class VerboseGarbageCollectorRunner { + + private static Map stringContainer = new HashMap<>(); + + public static void main(String[] args) { + System.out.println("Start of program!"); + String stringWithPrefix = "stringWithPrefix"; + + // Load Java Heap with 3 M java.lang.String instances + for (int i = 0; i < 3000000; i++) { + String newString = stringWithPrefix + i; + stringContainer.put(newString, newString); + } + System.out.println("MAP size: " + stringContainer.size()); + + // Explicit GC! + System.gc(); + + // Remove 2 M out of 3 M + for (int i = 0; i < 2000000; i++) { + String newString = stringWithPrefix + i; + stringContainer.remove(newString); + } + + System.out.println("MAP size: " + stringContainer.size()); + System.out.println("End of program!"); + } + +} diff --git a/core-java/src/main/java/com/baeldung/heapdump/HeapDump.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/heapdump/HeapDump.java similarity index 100% rename from core-java/src/main/java/com/baeldung/heapdump/HeapDump.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/heapdump/HeapDump.java diff --git a/core-java/src/main/java/com/baeldung/jmx/Game.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/Game.java similarity index 100% rename from core-java/src/main/java/com/baeldung/jmx/Game.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/Game.java diff --git a/core-java/src/main/java/com/baeldung/jmx/GameMBean.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/GameMBean.java similarity index 100% rename from core-java/src/main/java/com/baeldung/jmx/GameMBean.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/GameMBean.java diff --git a/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java similarity index 100% rename from core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java old mode 100755 new mode 100644 similarity index 94% rename from core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java index e16d1ae6da..a5b5794238 --- a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java @@ -1,9 +1,9 @@ -package com.baeldung.memoryleaks.equalshashcode; - -public class Person { - public String name; - - public Person(String name) { - this.name = name; - } -} +package com.baeldung.memoryleaks.equalshashcode; + +public class Person { + public String name; + + public Person(String name) { + this.name = name; + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java old mode 100755 new mode 100644 similarity index 96% rename from core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java index 3af70dd1eb..3e54332264 --- a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java @@ -1,25 +1,25 @@ -package com.baeldung.memoryleaks.equalshashcode; - -public class PersonOptimized { - public String name; - - public PersonOptimized(String name) { - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof PersonOptimized)) { - return false; - } - PersonOptimized person = (PersonOptimized) o; - return person.name.equals(name); - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + name.hashCode(); - return result; - }} +package com.baeldung.memoryleaks.equalshashcode; + +public class PersonOptimized { + public String name; + + public PersonOptimized(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof PersonOptimized)) { + return false; + } + PersonOptimized person = (PersonOptimized) o; + return person.name.equals(name); + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + name.hashCode(); + return result; + }} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java old mode 100755 new mode 100644 similarity index 95% rename from core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java index ce77d883f6..07ed52e38d --- a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java @@ -1,32 +1,32 @@ -package com.baeldung.memoryleaks.finalize; - -import java.nio.charset.Charset; -import java.util.Random; - -public class BulkyObject { - private String data[]; - - public BulkyObject() { - data = new String[1000000]; - - for(int i=0; i<1000000; i++) { - data[i] = getRandomString(); - } - } - - private String getRandomString() { - byte[] array = new byte[1000]; - new Random().nextBytes(array); - return new String(array, Charset.forName("UTF-8")); - } - - @Override - public void finalize() { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("Finalizer called"); - } -} +package com.baeldung.memoryleaks.finalize; + +import java.nio.charset.Charset; +import java.util.Random; + +public class BulkyObject { + private String data[]; + + public BulkyObject() { + data = new String[1000000]; + + for(int i=0; i<1000000; i++) { + data[i] = getRandomString(); + } + } + + private String getRandomString() { + byte[] array = new byte[1000]; + new Random().nextBytes(array); + return new String(array, Charset.forName("UTF-8")); + } + + @Override + public void finalize() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Finalizer called"); + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java similarity index 96% rename from core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java index dc1302432e..8a8f2ae6c2 100644 --- a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java @@ -1,22 +1,22 @@ -package com.baeldung.memoryleaks.finalize; - -import java.nio.charset.Charset; -import java.util.Random; - -public class BulkyObjectOptimized { - private String data[]; - - public BulkyObjectOptimized() { - data = new String[1000000]; - - for(int i=0; i<1000000; i++) { - data[i] = getRandomString(); - } - } - - private String getRandomString() { - byte[] array = new byte[1000]; - new Random().nextBytes(array); - return new String(array, Charset.forName("UTF-8")); - } -} +package com.baeldung.memoryleaks.finalize; + +import java.nio.charset.Charset; +import java.util.Random; + +public class BulkyObjectOptimized { + private String data[]; + + public BulkyObjectOptimized() { + data = new String[1000000]; + + for(int i=0; i<1000000; i++) { + data[i] = getRandomString(); + } + } + + private String getRandomString() { + byte[] array = new byte[1000]; + new Random().nextBytes(array); + return new String(array, Charset.forName("UTF-8")); + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java old mode 100755 new mode 100644 similarity index 95% rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java index bbd5310182..47801878f8 --- a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java @@ -1,22 +1,22 @@ -package com.baeldung.memoryleaks.innerclass; - -import java.nio.charset.Charset; -import java.util.Random; - -public class BulkyObject { - private String data[]; - - public BulkyObject() { - data = new String[1000000]; - - for(int i=0; i<1000000; i++) { - data[i] = getRandomString(); - } - } - - private String getRandomString() { - byte[] array = new byte[1000]; - new Random().nextBytes(array); - return new String(array, Charset.forName("UTF-8")); - } -} +package com.baeldung.memoryleaks.innerclass; + +import java.nio.charset.Charset; +import java.util.Random; + +public class BulkyObject { + private String data[]; + + public BulkyObject() { + data = new String[1000000]; + + for(int i=0; i<1000000; i++) { + data[i] = getRandomString(); + } + } + + private String getRandomString() { + byte[] array = new byte[1000]; + new Random().nextBytes(array); + return new String(array, Charset.forName("UTF-8")); + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java old mode 100755 new mode 100644 similarity index 97% rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java index 06f928bc4a..e3e4506397 --- a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java @@ -1,17 +1,17 @@ -package com.baeldung.memoryleaks.innerclass; - -public class InnerClassDriver { - public static InnerClassWrapper.SimpleInnerClass getSimpleInnerClassObj() { - return new InnerClassWrapper().new SimpleInnerClass(); - } - - public static void main2(String[] args) { - InnerClassWrapper.SimpleInnerClass simpleInnerClassObj = getSimpleInnerClassObj(); - System.out.println("Debug point"); - } - - public static void main(String[] args) { - StaticNestedClassWrapper.StaticNestedClass simpleInnerClassObj = new StaticNestedClassWrapper.StaticNestedClass(); - System.out.println("Debug point"); - } -} +package com.baeldung.memoryleaks.innerclass; + +public class InnerClassDriver { + public static InnerClassWrapper.SimpleInnerClass getSimpleInnerClassObj() { + return new InnerClassWrapper().new SimpleInnerClass(); + } + + public static void main2(String[] args) { + InnerClassWrapper.SimpleInnerClass simpleInnerClassObj = getSimpleInnerClassObj(); + System.out.println("Debug point"); + } + + public static void main(String[] args) { + StaticNestedClassWrapper.StaticNestedClass simpleInnerClassObj = new StaticNestedClassWrapper.StaticNestedClass(); + System.out.println("Debug point"); + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java old mode 100755 new mode 100644 similarity index 95% rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java index 25fecf9bb3..97b05ea02e --- a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java @@ -1,10 +1,10 @@ -package com.baeldung.memoryleaks.innerclass; - - -public class InnerClassWrapper { - private BulkyObject bulkyObject = new BulkyObject(); - - public class SimpleInnerClass { - - } -} +package com.baeldung.memoryleaks.innerclass; + + +public class InnerClassWrapper { + private BulkyObject bulkyObject = new BulkyObject(); + + public class SimpleInnerClass { + + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java old mode 100755 new mode 100644 similarity index 95% rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java index d1729d78a3..c37e08a049 --- a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java +++ b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java @@ -1,10 +1,10 @@ -package com.baeldung.memoryleaks.innerclass; - - -public class StaticNestedClassWrapper { - private BulkyObject bulkyObject = new BulkyObject(); - - public static class StaticNestedClass { - - } -} +package com.baeldung.memoryleaks.innerclass; + + +public class StaticNestedClassWrapper { + private BulkyObject bulkyObject = new BulkyObject(); + + public static class StaticNestedClass { + + } +} diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java similarity index 100% rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java similarity index 100% rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java similarity index 100% rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java similarity index 100% rename from core-java/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java similarity index 100% rename from core-java/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java diff --git a/core-java/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java b/core-java-modules/core-java-perf/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java similarity index 100% rename from core-java/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java rename to core-java-modules/core-java-perf/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java diff --git a/core-java-modules/core-java-perf/src/main/resources/logback.xml b/core-java-modules/core-java-perf/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-perf/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java b/core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java rename to core-java-modules/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java diff --git a/core-java-modules/core-java-reflection/README.MD b/core-java-modules/core-java-reflection/README.MD new file mode 100644 index 0000000000..c8766d6858 --- /dev/null +++ b/core-java-modules/core-java-reflection/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Void Type in Java](https://www.baeldung.com/java-void-type) diff --git a/core-java-modules/core-java-reflection/pom.xml b/core-java-modules/core-java-reflection/pom.xml new file mode 100644 index 0000000000..e6c7f81d6c --- /dev/null +++ b/core-java-modules/core-java-reflection/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + core-java-reflection + 0.1.0-SNAPSHOT + core-java-reflection + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.assertj + assertj-core + ${assertj-core.version} + + + + + 3.10.0 + + \ No newline at end of file diff --git a/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java new file mode 100644 index 0000000000..1459bf25c5 --- /dev/null +++ b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Action.java @@ -0,0 +1,5 @@ +package com.baeldung.reflection.voidtype; + +public interface Action { + void execute(); +} diff --git a/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java new file mode 100644 index 0000000000..dcfbe72008 --- /dev/null +++ b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Calculator.java @@ -0,0 +1,21 @@ +package com.baeldung.reflection.voidtype; + +public class Calculator { + private int result = 0; + + public int add(int number) { + return result += number; + } + + public int sub(int number) { + return result -= number; + } + + public void clear() { + result = 0; + } + + public void print() { + System.out.println(result); + } +} diff --git a/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java new file mode 100644 index 0000000000..09817199fa --- /dev/null +++ b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/Defer.java @@ -0,0 +1,27 @@ +package com.baeldung.reflection.voidtype; + +import java.util.concurrent.Callable; +import java.util.function.Consumer; +import java.util.function.Function; + +public class Defer { + public static V defer(Callable callable) throws Exception { + return callable.call(); + } + + public static void defer(Runnable runnable) { + runnable.run(); + } + + public static R defer(Function function, T arg) { + return function.apply(arg); + } + + public static void defer(Consumer consumer, T arg) { + consumer.accept(arg); + } + + public static void defer(Action action) { + action.execute(); + } +} diff --git a/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java new file mode 100644 index 0000000000..47468ee641 --- /dev/null +++ b/core-java-modules/core-java-reflection/src/main/java/com/baeldung/reflection/voidtype/MyOwnDefer.java @@ -0,0 +1,15 @@ +package com.baeldung.reflection.voidtype; + +import java.util.concurrent.Callable; + +public class MyOwnDefer { + public static void defer(Runnable runnable) throws Exception { + Defer.defer(new Callable() { + @Override + public Void call() { + runnable.run(); + return null; + } + }); + } +} diff --git a/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java new file mode 100644 index 0000000000..0ba22bf6e3 --- /dev/null +++ b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/CalculatorUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.reflection.voidtype; + +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +class CalculatorUnitTest { + @Test + void givenCalculator_whenGettingVoidMethodsByReflection_thenOnlyClearAndPrint() { + Method[] calculatorMethods = Calculator.class.getDeclaredMethods(); + List calculatorVoidMethods = Arrays.stream(calculatorMethods) + .filter(method -> method.getReturnType().equals(Void.TYPE)) + .collect(Collectors.toList()); + + assertThat(calculatorVoidMethods) + .allMatch(method -> Arrays.asList("clear", "print").contains(method.getName())); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java new file mode 100644 index 0000000000..e2dc68effc --- /dev/null +++ b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/DeferUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.reflection.voidtype; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.function.Function; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class DeferUnitTest { + @Test + void givenVoidCallable_whenDiffer_thenReturnNull() throws Exception { + Callable callable = new Callable() { + @Override + public Void call() { + System.out.println("Hello!"); + return null; + } + }; + + assertThat(Defer.defer(callable)).isNull(); + } + + @Test + void givenVoidRunnable_whenDiffer_thenNoReturn() { + AtomicBoolean run = new AtomicBoolean(false); + + Runnable runnable = new Runnable() { + @Override + public void run() { + System.out.println("Hello!"); + run.set(true); + } + }; + + Defer.defer(runnable); + + assertTrue(run.get()); + } + + @Test + void givenVoidFunction_whenDiffer_thenReturnNull() { + Function function = s -> { + System.out.println("Hello " + s + "!"); + return null; + }; + + assertThat(Defer.defer(function, "World")).isNull(); + } + + @Test + void givenVoidConsumer_whenDiffer_thenReturnNull() { + AtomicBoolean run = new AtomicBoolean(false); + + Consumer function = s -> { + System.out.println("Hello " + s + "!"); + run.set(true); + }; + + Defer.defer(function, "World"); + + assertTrue(run.get()); + } + + @Test + void givenAction_whenDiffer_thenNoReturn() { + AtomicBoolean run = new AtomicBoolean(false); + + Action action = () -> { + System.out.println("Hello!"); + run.set(true); + }; + + Defer.defer(action); + + assertTrue(run.get()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java new file mode 100644 index 0000000000..e3c3612a22 --- /dev/null +++ b/core-java-modules/core-java-reflection/src/test/java/com/baeldung/reflection/voidtype/MyOwnDeferUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.reflection.voidtype; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.jupiter.api.Assertions.*; + +class MyOwnDeferUnitTest { + @Test + void defer() throws Exception { + AtomicBoolean run = new AtomicBoolean(false); + Runnable runnable = () -> { + System.out.println("Hello!"); + run.set(true); + }; + + MyOwnDefer.defer(runnable); + + assertTrue(run.get()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-security/README.md b/core-java-modules/core-java-security/README.md new file mode 100644 index 0000000000..9526b15be5 --- /dev/null +++ b/core-java-modules/core-java-security/README.md @@ -0,0 +1,12 @@ +## Core Java Security + +### Relevant Articles: +- [MD5 Hashing in Java](http://www.baeldung.com/java-md5) +- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class) +- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl) +- [Java KeyStore API](http://www.baeldung.com/java-keystore) +- [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 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) diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml new file mode 100644 index 0000000000..ed82a5209a --- /dev/null +++ b/core-java-modules/core-java-security/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + com.baeldung + core-java-security + 0.1.0-SNAPSHOT + core-java-security + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + + + + + 3.8.1 + 1.60 + 1.11 + + + 3.10.0 + + + + diff --git a/core-java/src/main/java/com/baeldung/cipher/Encryptor.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/cipher/Encryptor.java similarity index 100% rename from core-java/src/main/java/com/baeldung/cipher/Encryptor.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/cipher/Encryptor.java diff --git a/core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java similarity index 100% rename from core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java new file mode 100644 index 0000000000..94dd22ff4b --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java @@ -0,0 +1,9 @@ +package com.baeldung.hashing; + +public class DigestAlgorithms { + + public static final String SHA3_256 = "SHA3-256"; + public static final String SHA_256 = "SHA-256"; + public static final String KECCAK_256 = "Keccak-256"; + +} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java new file mode 100644 index 0000000000..19fc4cf059 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java @@ -0,0 +1,30 @@ +package com.baeldung.hashing; + +import org.bouncycastle.jcajce.provider.digest.Keccak; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class Keccak256Hashing { + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(KECCAK_256); + final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(encodedhash); + } + + public static String hashWithBouncyCastle(final String originalString) { + Keccak.Digest256 digest256 = new Keccak.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java similarity index 67% rename from core-java/src/main/java/com/baeldung/hashing/SHA256Hashing.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java index 4fa164cadc..ec008cebab 100644 --- a/core-java/src/main/java/com/baeldung/hashing/SHA256Hashing.java +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java @@ -8,15 +8,18 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import static com.baeldung.hashing.DigestAlgorithms.SHA_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + public class SHA256Hashing { public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); + final MessageDigest digest = MessageDigest.getInstance(SHA_256); final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); return bytesToHex(encodedhash); } - public static String HashWithGuava(final String originalString) { + public static String hashWithGuava(final String originalString) { final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString(); return sha256hex; } @@ -27,20 +30,10 @@ public class SHA256Hashing { } public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException { - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); + final MessageDigest digest = MessageDigest.getInstance(SHA_256); final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); final String sha256hex = new String(Hex.encode(hash)); return sha256hex; } - private static String bytesToHex(byte[] hash) { - StringBuffer hexString = new StringBuffer(); - for (int i = 0; i < hash.length; i++) { - String hex = Integer.toHexString(0xff & hash[i]); - if (hex.length() == 1) - hexString.append('0'); - hexString.append(hex); - } - return hexString.toString(); - } } diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java new file mode 100644 index 0000000000..eb363205b1 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java @@ -0,0 +1,45 @@ +package com.baeldung.hashing; + +import com.google.common.hash.Hashing; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.crypto.digests.SHA3Digest; +import org.bouncycastle.jcajce.provider.digest.SHA3; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.encoders.Hex; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import static com.baeldung.hashing.DigestAlgorithms.SHA3_256; +import static com.baeldung.hashing.SHACommonUtils.bytesToHex; + +public class SHA3Hashing { + + /* works with JDK9+ only */ + public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException { + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException { + Security.addProvider(new BouncyCastleProvider()); + final MessageDigest digest = MessageDigest.getInstance(SHA3_256); + final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(hashbytes); + } + + /* works with JDK9+ only */ + public static String hashWithApacheCommonsJDK9(final String originalString) { + return new DigestUtils(SHA3_256).digestAsHex(originalString); + } + + public static String hashWithBouncyCastle(final String originalString) { + SHA3.Digest256 digest256 = new SHA3.Digest256(); + byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8)); + return new String(Hex.encode(hashbytes)); + } + +} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java new file mode 100644 index 0000000000..0f28408083 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java @@ -0,0 +1,16 @@ +package com.baeldung.hashing; + +class SHACommonUtils { + + public static String bytesToHex(byte[] hash) { + StringBuffer hexString = new StringBuffer(); + for (byte h : hash) { + String hex = Integer.toHexString(0xff & h); + if (hex.length() == 1) + hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } + +} diff --git a/core-java/src/main/java/com/baeldung/keystore/JavaKeyStore.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/keystore/JavaKeyStore.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keystore/JavaKeyStore.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/keystore/JavaKeyStore.java diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java similarity index 100% rename from core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java similarity index 100% rename from core-java/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java similarity index 100% rename from core-java/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/random/SecureRandomDemo.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/random/SecureRandomDemo.java new file mode 100644 index 0000000000..02f815f5a7 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/random/SecureRandomDemo.java @@ -0,0 +1,36 @@ +package com.baeldung.random; + +import java.security.SecureRandom; +import java.security.NoSuchAlgorithmException; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.DoubleStream; + +public interface SecureRandomDemo { + + public static void generateSecureRandomValues() { + SecureRandom sr = new SecureRandom(); + + int randomInt = sr.nextInt(); + long randomLong = sr.nextLong(); + float randomFloat = sr.nextFloat(); + double randomDouble = sr.nextDouble(); + boolean randomBoolean = sr.nextBoolean(); + + IntStream randomIntStream = sr.ints(); + LongStream randomLongStream = sr.longs(); + DoubleStream randomDoubleStream = sr.doubles(); + + byte[] values = new byte[124]; + sr.nextBytes(values); + } + + public static SecureRandom getSecureRandomForAlgorithm(String algorithm) throws NoSuchAlgorithmException { + if (algorithm == null || algorithm.isEmpty()) { + return new SecureRandom(); + } + + return SecureRandom.getInstance(algorithm); + } + +} diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java new file mode 100644 index 0000000000..aa70b11584 --- /dev/null +++ b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java @@ -0,0 +1,115 @@ +package com.baeldung.ssl; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EnableTLSv12 { + + private final Logger logger = LoggerFactory.getLogger(EnableTLSv12.class); + + public String url = ""; + public Integer port = null; + + public EnableTLSv12() { + } + + public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException { + EnableTLSv12 enableTLSv12 = new EnableTLSv12(); + if (args.length != 2) { + System.out.println("Provide the server url and the secure port:"); + System.exit(-1); + } + enableTLSv12.setHost(args); + enableTLSv12.setPort(args); + enableTLSv12.enableTLSv12UsingHttpConnection(); + enableTLSv12.enableTLSv12UsingProtocol(); + enableTLSv12.enableTLSv12UsingSSLContext(); + enableTLSv12.enableTLSv12UsingSSLParameters(); + } + + private void setPort(String[] args) { + url = args[0]; + } + + private void setHost(String[] args) { + String portNumber = args[1]; + port = Integer.parseInt(portNumber); + } + + private void handleCommunication(SSLSocket socket, String usedTLSProcess) throws IOException { + logger.debug("Enabled TLS v1.2 on " + usedTLSProcess); + try (PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { + out.println("GET / HTTP/1.0"); + out.println(); + out.flush(); + if (out.checkError()) { + logger.error("SSLSocketClient: java.io.PrintWriter error"); + return; + } + + String inputLine; + while ((inputLine = in.readLine()) != null) + logger.info(inputLine); + } + } + + public void enableTLSv12UsingSSLParameters() throws UnknownHostException, IOException { + SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(url.trim(), port); + SSLParameters params = new SSLParameters(); + params.setProtocols(new String[] { "TLSv1.2" }); + sslSocket.setSSLParameters(params); + sslSocket.startHandshake(); + handleCommunication(sslSocket, "SSLSocketFactory-SSLParameters"); + } + + public void enableTLSv12UsingProtocol() throws IOException { + SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(url, port); + sslSocket.setEnabledProtocols(new String[] { "TLSv1.2" }); + sslSocket.startHandshake(); + handleCommunication(sslSocket, "SSLSocketFactory-EnabledProtocols"); + } + + public void enableTLSv12UsingHttpConnection() throws IOException, NoSuchAlgorithmException, KeyManagementException { + URL urls = new URL("https://" + url + ":" + port); + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, null, new SecureRandom()); + HttpsURLConnection connection = (HttpsURLConnection) urls.openConnection(); + connection.setSSLSocketFactory(sslContext.getSocketFactory()); + try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String input; + while ((input = br.readLine()) != null) { + logger.info(input); + } + } + logger.debug("Created TLSv1.2 connection on HttpsURLConnection"); + } + + public void enableTLSv12UsingSSLContext() throws NoSuchAlgorithmException, KeyManagementException, UnknownHostException, IOException { + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, null, new SecureRandom()); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(url, port); + handleCommunication(socket, "SSLContext"); + } + +} diff --git a/core-java/src/main/java/com/baeldung/ssl/SecureConnection.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java similarity index 100% rename from core-java/src/main/java/com/baeldung/ssl/SecureConnection.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java diff --git a/core-java/src/main/java/com/baeldung/ssl/example/SimpleClient.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java similarity index 100% rename from core-java/src/main/java/com/baeldung/ssl/example/SimpleClient.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java diff --git a/core-java/src/main/java/com/baeldung/ssl/example/SimpleServer.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/ssl/example/SimpleServer.java rename to core-java-modules/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java diff --git a/core-java-modules/core-java-security/src/main/resources/logback.xml b/core-java-modules/core-java-security/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-security/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java new file mode 100644 index 0000000000..9ed35c8834 --- /dev/null +++ b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Keccak256HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016"; + + @Test public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test public void testHashWithBouncyCastle() { + final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java similarity index 76% rename from core-java/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java index 3c34bf2c6e..6bc9ad2cc6 100644 --- a/core-java/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java +++ b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java @@ -12,24 +12,24 @@ public class SHA256HashingUnitTest { @Test public void testHashWithJavaMessageDigest() throws Exception { final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue); - assertEquals(currentHashedValue, hashedValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithGuava() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); - assertEquals(currentHashedValue, hashedValue); + final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithApacheCommans() throws Exception { - final String currentHashedValue = SHA256Hashing.HashWithGuava(originalValue); - assertEquals(currentHashedValue, hashedValue); + final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue); + assertEquals(hashedValue, currentHashedValue); } @Test public void testHashWithBouncyCastle() throws Exception { final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue); - assertEquals(currentHashedValue, hashedValue); + assertEquals(hashedValue, currentHashedValue); } } \ No newline at end of file diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java new file mode 100644 index 0000000000..fffab96405 --- /dev/null +++ b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.hashing; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SHA3HashingUnitTest { + + private static String originalValue = "abc123"; + private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee"; + + /* works with JDK9+ only */ + //@Test + public void testHashWithJavaMessageDigestJDK9() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithJavaMessageDigest() throws Exception { + final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + /* works with JDK9+ only */ + //@Test + public void testHashWithApacheCommonsJDK9() { + final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + + @Test + public void testHashWithBouncyCastle() { + final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue); + assertEquals(hashedValue, currentHashedValue); + } + +} diff --git a/core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java similarity index 87% rename from core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java index cb2a9f1c49..7473c52a35 100644 --- a/core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java +++ b/core-java-modules/core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java @@ -4,15 +4,24 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; + import sun.security.x509.AlgorithmId; import sun.security.x509.CertificateAlgorithmId; import sun.security.x509.CertificateSerialNumber; import sun.security.x509.CertificateValidity; import sun.security.x509.CertificateVersion; import sun.security.x509.CertificateX509Key; +import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertInfo; +import sun.security.x509.CertificateExtensions; +import sun.security.x509.GeneralNames; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNameInterface; +import sun.security.x509.DNSName; +import sun.security.x509.IPAddressName; +import sun.security.util.DerOutputStream; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; @@ -188,6 +197,23 @@ public class JavaKeyStoreUnitTest { Date validTo = new Date(validFrom.getTime() + 50L * 365L * 24L * 60L * 60L * 1000L); //50 years CertificateValidity validity = new CertificateValidity(validFrom, validTo); certInfo.set(X509CertInfo.VALIDITY, validity); + + GeneralNameInterface dnsName = new DNSName("baeldung.com"); + DerOutputStream dnsNameOutputStream = new DerOutputStream(); + dnsName.encode(dnsNameOutputStream); + + GeneralNameInterface ipAddress = new IPAddressName("127.0.0.1"); + DerOutputStream ipAddressOutputStream = new DerOutputStream(); + ipAddress.encode(ipAddressOutputStream); + + GeneralNames generalNames = new GeneralNames(); + generalNames.add(new GeneralName(dnsName)); + generalNames.add(new GeneralName(ipAddress)); + + CertificateExtensions ext = new CertificateExtensions(); + ext.set(SubjectAlternativeNameExtension.NAME, new SubjectAlternativeNameExtension(generalNames)); + + certInfo.set(X509CertInfo.EXTENSIONS, ext); // Create certificate and sign it X509CertImpl cert = new X509CertImpl(certInfo); @@ -202,4 +228,5 @@ public class JavaKeyStoreUnitTest { return newCert; } + } \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java rename to core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java rename to core-java-modules/core-java-security/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java diff --git a/core-java/src/test/resources/test_md5.txt b/core-java-modules/core-java-security/src/test/resources/test_md5.txt similarity index 100% rename from core-java/src/test/resources/test_md5.txt rename to core-java-modules/core-java-security/src/test/resources/test_md5.txt diff --git a/core-java-modules/core-java-sun/.gitignore b/core-java-modules/core-java-sun/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/core-java-modules/core-java-sun/.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-sun/README.md b/core-java-modules/core-java-sun/README.md similarity index 71% rename from core-java-sun/README.md rename to core-java-modules/core-java-sun/README.md index 9cf8b26f1b..e2dba76b41 100644 --- a/core-java-sun/README.md +++ b/core-java-modules/core-java-sun/README.md @@ -4,3 +4,4 @@ ### Relevant Articles: - [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) +- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe) \ No newline at end of file diff --git a/core-java-sun/pom.xml b/core-java-modules/core-java-sun/pom.xml similarity index 98% rename from core-java-sun/pom.xml rename to core-java-modules/core-java-sun/pom.xml index 57d5e9da5b..da27564d96 100644 --- a/core-java-sun/pom.xml +++ b/core-java-modules/core-java-sun/pom.xml @@ -4,14 +4,14 @@ com.baeldung core-java-sun 0.1.0-SNAPSHOT - jar core-java-sun + jar com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java @@ -261,8 +261,6 @@ - - 2.8.5 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-modules/core-java-sun/src/main/java/com/baeldung/.gitignore b/core-java-modules/core-java-sun/src/main/java/com/baeldung/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-modules/core-java-sun/src/main/java/com/baeldung/.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/core-java-modules/core-java-sun/src/main/java/com/baeldung/README.md b/core-java-modules/core-java-sun/src/main/java/com/baeldung/README.md new file mode 100644 index 0000000000..7d843af9ea --- /dev/null +++ b/core-java-modules/core-java-sun/src/main/java/com/baeldung/README.md @@ -0,0 +1 @@ +### Relevant Articles: diff --git a/core-java-sun/src/main/java/com/baeldung/javac/Positive.java b/core-java-modules/core-java-sun/src/main/java/com/baeldung/javac/Positive.java similarity index 100% rename from core-java-sun/src/main/java/com/baeldung/javac/Positive.java rename to core-java-modules/core-java-sun/src/main/java/com/baeldung/javac/Positive.java diff --git a/core-java-sun/src/main/java/com/baeldung/javac/SampleJavacPlugin.java b/core-java-modules/core-java-sun/src/main/java/com/baeldung/javac/SampleJavacPlugin.java similarity index 100% rename from core-java-sun/src/main/java/com/baeldung/javac/SampleJavacPlugin.java rename to core-java-modules/core-java-sun/src/main/java/com/baeldung/javac/SampleJavacPlugin.java diff --git a/core-java-sun/src/main/resources/META-INF/services/com.sun.source.util.Plugin b/core-java-modules/core-java-sun/src/main/resources/META-INF/services/com.sun.source.util.Plugin similarity index 100% rename from core-java-sun/src/main/resources/META-INF/services/com.sun.source.util.Plugin rename to core-java-modules/core-java-sun/src/main/resources/META-INF/services/com.sun.source.util.Plugin diff --git a/core-java-sun/src/main/resources/log4j.properties b/core-java-modules/core-java-sun/src/main/resources/log4j.properties similarity index 100% rename from core-java-sun/src/main/resources/log4j.properties rename to core-java-modules/core-java-sun/src/main/resources/log4j.properties diff --git a/core-java-modules/core-java-sun/src/main/resources/logback.xml b/core-java-modules/core-java-sun/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-sun/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-sun/src/test/java/com/baeldung/javac/SampleJavacPluginIntegrationTest.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SampleJavacPluginIntegrationTest.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/SampleJavacPluginIntegrationTest.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SampleJavacPluginIntegrationTest.java diff --git a/core-java-sun/src/test/java/com/baeldung/javac/SimpleClassFile.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleClassFile.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/SimpleClassFile.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleClassFile.java diff --git a/core-java-sun/src/test/java/com/baeldung/javac/SimpleFileManager.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleFileManager.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/SimpleFileManager.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleFileManager.java diff --git a/core-java-sun/src/test/java/com/baeldung/javac/SimpleSourceFile.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleSourceFile.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/SimpleSourceFile.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/SimpleSourceFile.java diff --git a/core-java-sun/src/test/java/com/baeldung/javac/TestCompiler.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/TestCompiler.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/TestCompiler.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/TestCompiler.java diff --git a/core-java-sun/src/test/java/com/baeldung/javac/TestRunner.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/TestRunner.java similarity index 100% rename from core-java-sun/src/test/java/com/baeldung/javac/TestRunner.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/javac/TestRunner.java diff --git a/core-java/src/test/java/com/baeldung/unsafe/CASCounter.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/CASCounter.java similarity index 100% rename from core-java/src/test/java/com/baeldung/unsafe/CASCounter.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/CASCounter.java diff --git a/core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/OffHeapArray.java similarity index 100% rename from core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/OffHeapArray.java diff --git a/core-java/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java b/core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java rename to core-java-modules/core-java-sun/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java diff --git a/core-java-modules/core-java-sun/src/test/resources/.gitignore b/core-java-modules/core-java-sun/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-modules/core-java-sun/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/core-java-modules/core-java/.gitignore b/core-java-modules/core-java/.gitignore new file mode 100644 index 0000000000..374c8bf907 --- /dev/null +++ b/core-java-modules/core-java/.gitignore @@ -0,0 +1,25 @@ +*.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 +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml \ No newline at end of file diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md new file mode 100644 index 0000000000..b32b5d5cd9 --- /dev/null +++ b/core-java-modules/core-java/README.md @@ -0,0 +1,55 @@ +========= + +## Core Java Cookbooks and Examples + +### Relevant Articles: +- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) +- [How to Run a Shell Command in Java](http://www.baeldung.com/run-shell-command-in-java) +- [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java) +- [A Guide To Java Regular Expressions API](http://www.baeldung.com/regular-expressions-java) +- [Getting Started with Java Properties](http://www.baeldung.com/java-properties) +- [Pattern Search with Grep in Java](http://www.baeldung.com/grep-in-java) +- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven) +- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) +- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) +- [JVM Log Forging](http://www.baeldung.com/jvm-log-forging) +- [How to Add a Single Element to a Stream](http://www.baeldung.com/java-stream-append-prepend) +- [How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) +- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) +- [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) +- [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) +- [Introduction to Javadoc](http://www.baeldung.com/javadoc) +- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable) +- [How to Detect the OS Using Java](http://www.baeldung.com/java-detect-os) +- [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) +- [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) +- [Guide to the 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) +- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) +- [Guide to Java Instrumentation](http://www.baeldung.com/java-instrumentation) +- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) +- [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception) +- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) +- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) +- [Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) +- [Abstract Classes in Java](https://www.baeldung.com/java-abstract-class) +- [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) +- [Graphs in Java](https://www.baeldung.com/java-graphs) +- [Console I/O in Java](http://www.baeldung.com/java-console-input-output) +- [Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) +- [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) +- [Introduction to Basic Syntax in Java](https://www.baeldung.com/java-syntax) +- [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) +- [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) +- [How to Find an Exception’s Root Cause in Java](https://www.baeldung.com/java-exception-root-cause) +- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) diff --git a/core-java/customers.xml b/core-java-modules/core-java/customers.xml similarity index 100% rename from core-java/customers.xml rename to core-java-modules/core-java/customers.xml diff --git a/core-java/externalizable.txt b/core-java-modules/core-java/externalizable.txt similarity index 100% rename from core-java/externalizable.txt rename to core-java-modules/core-java/externalizable.txt diff --git a/core-java/pom.xml b/core-java-modules/core-java/pom.xml similarity index 92% rename from core-java/pom.xml rename to core-java-modules/core-java/pom.xml index 64345ab14c..2f33212c38 100644 --- a/core-java/pom.xml +++ b/core-java-modules/core-java/pom.xml @@ -10,7 +10,7 @@ com.baeldung parent-java 0.0.1-SNAPSHOT - ../parent-java + ../../parent-java @@ -24,11 +24,6 @@ commons-lang3 ${commons-lang3.version} - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - org.unix4j unix4j-command @@ -75,12 +70,6 @@ ${assertj-core.version} test - - - commons-codec - commons-codec - ${commons-codec.version} - org.javamoney moneta @@ -121,32 +110,11 @@ jmh-generator-annprocess ${jmh-generator-annprocess.version} - - org.springframework - spring-web - ${springframework.spring-web.version} - com.h2database h2 ${h2database.version} - - javax.mail - mail - ${javax.mail.version} - - - - org.apache.tika - tika-core - ${tika.version} - - - net.sf.jmimemagic - jmimemagic - ${jmime-magic.version} - org.javassist @@ -482,19 +450,15 @@ - 2.8.5 2.8.2 - 3.5 - 1.55 - 1.10 + 3.9 2.5 3.6.1 1.0.3 0.4 1.8.7 - 1.16.12 4.6-b01 1.13 0.6.5 @@ -505,7 +469,6 @@ 2.21.0 - 4.3.4.RELEASE 1.1 1.4.197 @@ -514,16 +477,12 @@ 1.19 3.0.0-M1 - 1.5.0-b01 3.0.2 1.4.4 3.1.1 2.0.3.RELEASE 1.6.0 61.1 - - 1.18 - 0.1.5 3.21.0-GA diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/.gitignore b/core-java-modules/core-java/src/main/java/com/baeldung/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/.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/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java similarity index 97% rename from core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java rename to core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java index 3180762227..5b250635ea 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java @@ -1,29 +1,29 @@ -package com.baeldung.abstractclasses.application; - -import com.baeldung.abstractclasses.filereaders.BaseFileReader; -import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; -import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class Application { - - public static void main(String[] args) throws IOException, URISyntaxException { - - Application application = new Application(); - Path path = application.getPathFromResourcesFile("files/test.txt"); - BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); - lowercaseFileReader.readFile().forEach(line -> System.out.println(line)); - - BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); - uppercaseFileReader.readFile().forEach(line -> System.out.println(line)); - - } - - private Path getPathFromResourcesFile(String filePath) throws URISyntaxException { - return Paths.get(getClass().getClassLoader().getResource(filePath).toURI()); - - } -} +package com.baeldung.abstractclasses.application; + +import com.baeldung.abstractclasses.filereaders.BaseFileReader; +import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; +import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Application { + + public static void main(String[] args) throws IOException, URISyntaxException { + + Application application = new Application(); + Path path = application.getPathFromResourcesFile("files/test.txt"); + BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); + lowercaseFileReader.readFile().forEach(line -> System.out.println(line)); + + BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); + uppercaseFileReader.readFile().forEach(line -> System.out.println(line)); + + } + + private Path getPathFromResourcesFile(String filePath) throws URISyntaxException { + return Paths.get(getClass().getClassLoader().getResource(filePath).toURI()); + + } +} diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java similarity index 96% rename from core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java index 97452a9eca..376147aa13 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java @@ -1,27 +1,27 @@ -package com.baeldung.abstractclasses.filereaders; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Collectors; - -public abstract class BaseFileReader { - - protected Path filePath; - - protected BaseFileReader(Path filePath) { - this.filePath = filePath; - } - - public Path getFilePath() { - return filePath; - } - - public List readFile() throws IOException { - return Files.lines(filePath) - .map(this::mapFileLine).collect(Collectors.toList()); - } - - protected abstract String mapFileLine(String line); -} +package com.baeldung.abstractclasses.filereaders; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class BaseFileReader { + + protected Path filePath; + + protected BaseFileReader(Path filePath) { + this.filePath = filePath; + } + + public Path getFilePath() { + return filePath; + } + + public List readFile() throws IOException { + return Files.lines(filePath) + .map(this::mapFileLine).collect(Collectors.toList()); + } + + protected abstract String mapFileLine(String line); +} diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java similarity index 95% rename from core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java index 53820d393c..33a3e098a0 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java @@ -1,15 +1,15 @@ -package com.baeldung.abstractclasses.filereaders; - -import java.nio.file.Path; - -public class LowercaseFileReader extends BaseFileReader { - - public LowercaseFileReader(Path filePath) { - super(filePath); - } - - @Override - public String mapFileLine(String line) { - return line.toLowerCase(); - } -} +package com.baeldung.abstractclasses.filereaders; + +import java.nio.file.Path; + +public class LowercaseFileReader extends BaseFileReader { + + public LowercaseFileReader(Path filePath) { + super(filePath); + } + + @Override + public String mapFileLine(String line) { + return line.toLowerCase(); + } +} diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java similarity index 95% rename from core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java index 3144a4f27f..4c93e75df7 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java @@ -1,15 +1,15 @@ -package com.baeldung.abstractclasses.filereaders; - -import java.nio.file.Path; - -public class UppercaseFileReader extends BaseFileReader { - - public UppercaseFileReader(Path filePath) { - super(filePath); - } - - @Override - public String mapFileLine(String line) { - return line.toUpperCase(); - } -} +package com.baeldung.abstractclasses.filereaders; + +import java.nio.file.Path; + +public class UppercaseFileReader extends BaseFileReader { + + public UppercaseFileReader(Path filePath) { + super(filePath); + } + + @Override + public String mapFileLine(String line) { + return line.toUpperCase(); + } +} diff --git a/core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java b/core-java-modules/core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java similarity index 100% rename from core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java rename to core-java-modules/core-java/src/main/java/com/baeldung/asciiart/AsciiArt.java diff --git a/core-java/src/main/java/com/baeldung/basicsyntax/SimpleAddition.java b/core-java-modules/core-java/src/main/java/com/baeldung/basicsyntax/SimpleAddition.java similarity index 100% rename from core-java/src/main/java/com/baeldung/basicsyntax/SimpleAddition.java rename to core-java-modules/core-java/src/main/java/com/baeldung/basicsyntax/SimpleAddition.java diff --git a/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java b/core-java-modules/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java similarity index 100% rename from core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java diff --git a/core-java/src/main/java/com/baeldung/classloader/PrintClassLoader.java b/core-java-modules/core-java/src/main/java/com/baeldung/classloader/PrintClassLoader.java similarity index 100% rename from core-java/src/main/java/com/baeldung/classloader/PrintClassLoader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/classloader/PrintClassLoader.java diff --git a/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java b/core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java similarity index 100% rename from core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java rename to core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java diff --git a/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java b/core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java similarity index 100% rename from core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java rename to core-java-modules/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java b/core-java-modules/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java new file mode 100644 index 0000000000..166b0ecb13 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java @@ -0,0 +1,29 @@ +package com.baeldung.curltojava; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class JavaCurlExamples { + + public static String inputStreamToString(InputStream inputStream) { + final int bufferSize = 8 * 1024; + byte[] buffer = new byte[bufferSize]; + final StringBuilder builder = new StringBuilder(); + try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream, bufferSize)) { + while (bufferedInputStream.read(buffer) != -1) { + builder.append(new String(buffer)); + } + } catch (IOException ex) { + Logger.getLogger(JavaCurlExamples.class.getName()).log(Level.SEVERE, null, ex); + } + return builder.toString(); + } + + public static void consumeInputStream(InputStream inputStream) { + inputStreamToString(inputStream); + } + +} diff --git a/core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java b/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java similarity index 100% rename from core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java rename to core-java-modules/core-java/src/main/java/com/baeldung/deserialization/AppleProduct.java diff --git a/core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java b/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java similarity index 100% rename from core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java rename to core-java-modules/core-java/src/main/java/com/baeldung/deserialization/DeserializationUtility.java diff --git a/core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java b/core-java-modules/core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java similarity index 100% rename from core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java rename to core-java-modules/core-java/src/main/java/com/baeldung/deserialization/SerializationUtility.java diff --git a/core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java b/core-java-modules/core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java similarity index 100% rename from core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java rename to core-java-modules/core-java/src/main/java/com/baeldung/encoding/CharacterEncodingExamples.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/Arithmetic.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ArrayIndexOutOfBounds.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/ClassCast.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ClassCast.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/FileNotFound.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/GlobalExceptionHandler.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/IllegalArgument.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/IllegalState.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/IllegalState.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/InterruptedExceptionExample.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/MalformedURL.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/NullPointer.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/NullPointer.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/NumberFormat.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/ParseExceptionExample.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/StackTraceToString.java diff --git a/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java similarity index 100% rename from core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/StringIndexOutOfBounds.java diff --git a/core-java/src/main/java/com/baeldung/executable/ExecutableMavenJar.java b/core-java-modules/core-java/src/main/java/com/baeldung/executable/ExecutableMavenJar.java similarity index 100% rename from core-java/src/main/java/com/baeldung/executable/ExecutableMavenJar.java rename to core-java-modules/core-java/src/main/java/com/baeldung/executable/ExecutableMavenJar.java diff --git a/core-java/src/main/java/com/baeldung/externalizable/Community.java b/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Community.java similarity index 100% rename from core-java/src/main/java/com/baeldung/externalizable/Community.java rename to core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Community.java diff --git a/core-java/src/main/java/com/baeldung/externalizable/Country.java b/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Country.java similarity index 100% rename from core-java/src/main/java/com/baeldung/externalizable/Country.java rename to core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Country.java diff --git a/core-java/src/main/java/com/baeldung/externalizable/Region.java b/core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Region.java similarity index 100% rename from core-java/src/main/java/com/baeldung/externalizable/Region.java rename to core-java-modules/core-java/src/main/java/com/baeldung/externalizable/Region.java diff --git a/core-java/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/fileparser/BufferedReaderExample.java diff --git a/core-java/src/main/java/com/baeldung/fileparser/FileReaderExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/fileparser/FileReaderExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/fileparser/FileReaderExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/fileparser/FileReaderExample.java diff --git a/core-java/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/fileparser/FilesReadLinesExample.java diff --git a/core-java/src/main/java/com/baeldung/fileparser/ScannerIntExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/fileparser/ScannerIntExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/fileparser/ScannerIntExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/fileparser/ScannerIntExample.java diff --git a/core-java/src/main/java/com/baeldung/fileparser/ScannerStringExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/fileparser/ScannerStringExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/fileparser/ScannerStringExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/fileparser/ScannerStringExample.java diff --git a/core-java/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java b/core-java-modules/core-java/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java similarity index 100% rename from core-java/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java rename to core-java-modules/core-java/src/main/java/com/baeldung/filesystem/jndi/LookupFSJNDI.java diff --git a/core-java/src/main/java/com/baeldung/graph/Graph.java b/core-java-modules/core-java/src/main/java/com/baeldung/graph/Graph.java similarity index 65% rename from core-java/src/main/java/com/baeldung/graph/Graph.java rename to core-java-modules/core-java/src/main/java/com/baeldung/graph/Graph.java index 43b5c0aa08..58713b1b3f 100644 --- a/core-java/src/main/java/com/baeldung/graph/Graph.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/graph/Graph.java @@ -19,7 +19,7 @@ public class Graph { void removeVertex(String label) { Vertex v = new Vertex(label); - adjVertices.values().stream().map(e -> e.remove(v)).collect(Collectors.toList()); + adjVertices.values().stream().forEach(e -> e.remove(v)); adjVertices.remove(new Vertex(label)); } @@ -59,18 +59,43 @@ public class Graph { Vertex(String label) { this.label = label; } - @Override - public boolean equals(Object obj) { - Vertex vertex = (Vertex) obj; - return vertex.label == label; - } + @Override public int hashCode() { - return label.hashCode(); + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + ((label == null) ? 0 : label.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; + Vertex other = (Vertex) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + return true; + } + @Override public String toString() { return label; } + + + private Graph getOuterType() { + return Graph.this; + } } } \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/graph/GraphTraversal.java b/core-java-modules/core-java/src/main/java/com/baeldung/graph/GraphTraversal.java similarity index 100% rename from core-java/src/main/java/com/baeldung/graph/GraphTraversal.java rename to core-java-modules/core-java/src/main/java/com/baeldung/graph/GraphTraversal.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/agent/AtmTransformer.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/agent/AtmTransformer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/agent/AtmTransformer.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/agent/AtmTransformer.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/agent/MyInstrumentationAgent.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/agent/MyInstrumentationAgent.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/agent/MyInstrumentationAgent.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/agent/MyInstrumentationAgent.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/application/AgentLoader.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/AgentLoader.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/application/AgentLoader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/AgentLoader.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/application/Launcher.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/Launcher.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/application/Launcher.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/Launcher.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtm.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtm.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/application/MyAtm.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtm.java diff --git a/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtmApplication.java b/core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtmApplication.java similarity index 100% rename from core-java/src/main/java/com/baeldung/instrumentation/application/MyAtmApplication.java rename to core-java-modules/core-java/src/main/java/com/baeldung/instrumentation/application/MyAtmApplication.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/jar/JarExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/jar/JarExample.java new file mode 100644 index 0000000000..5f33188adf --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/jar/JarExample.java @@ -0,0 +1,9 @@ +package com.baeldung.jar; + +public class JarExample { + + public static void main(String[] args) { + System.out.println("Hello Baeldung Reader!"); + } + +} diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/jar/example_manifest.txt b/core-java-modules/core-java/src/main/java/com/baeldung/jar/example_manifest.txt new file mode 100644 index 0000000000..90e83e9b42 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/jar/example_manifest.txt @@ -0,0 +1 @@ +Main-Class: com.baeldung.jar.JarExample diff --git a/core-java/src/main/java/com/baeldung/javac/Data.java b/core-java-modules/core-java/src/main/java/com/baeldung/javac/Data.java similarity index 100% rename from core-java/src/main/java/com/baeldung/javac/Data.java rename to core-java-modules/core-java/src/main/java/com/baeldung/javac/Data.java diff --git a/core-java/src/main/java/com/baeldung/javadoc/Person.java b/core-java-modules/core-java/src/main/java/com/baeldung/javadoc/Person.java similarity index 100% rename from core-java/src/main/java/com/baeldung/javadoc/Person.java rename to core-java-modules/core-java/src/main/java/com/baeldung/javadoc/Person.java diff --git a/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java b/core-java-modules/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java similarity index 100% rename from core-java/src/main/java/com/baeldung/javadoc/SuperHero.java rename to core-java-modules/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java diff --git a/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java b/core-java-modules/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java similarity index 100% rename from core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java rename to core-java-modules/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java diff --git a/core-java/src/main/java/com/baeldung/manifest/AppExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/manifest/AppExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/manifest/AppExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/manifest/AppExample.java diff --git a/core-java/src/main/java/com/baeldung/manifest/ExecuteJarFile.java b/core-java-modules/core-java/src/main/java/com/baeldung/manifest/ExecuteJarFile.java similarity index 100% rename from core-java/src/main/java/com/baeldung/manifest/ExecuteJarFile.java rename to core-java-modules/core-java/src/main/java/com/baeldung/manifest/ExecuteJarFile.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/manifest/MANIFEST.MF b/core-java-modules/core-java/src/main/java/com/baeldung/manifest/MANIFEST.MF new file mode 100644 index 0000000000..a363171952 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/manifest/MANIFEST.MF @@ -0,0 +1 @@ +Main-Class: com.baeldung.manifest.AppExample diff --git a/core-java/src/main/java/com/baeldung/money/JavaMoney.java b/core-java-modules/core-java/src/main/java/com/baeldung/money/JavaMoney.java similarity index 97% rename from core-java/src/main/java/com/baeldung/money/JavaMoney.java rename to core-java-modules/core-java/src/main/java/com/baeldung/money/JavaMoney.java index 3171d226ed..aa507071cf 100644 --- a/core-java/src/main/java/com/baeldung/money/JavaMoney.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/money/JavaMoney.java @@ -1,151 +1,151 @@ -package com.baeldung.money; - -import java.util.Locale; -import java.util.logging.Logger; - -import javax.money.CurrencyUnit; -import javax.money.Monetary; -import javax.money.MonetaryAmount; -import javax.money.UnknownCurrencyException; -import javax.money.convert.ConversionQueryBuilder; -import javax.money.convert.CurrencyConversion; -import javax.money.convert.MonetaryConversions; -import javax.money.format.AmountFormatQueryBuilder; -import javax.money.format.MonetaryAmountFormat; -import javax.money.format.MonetaryFormats; - -import org.javamoney.moneta.FastMoney; -import org.javamoney.moneta.Money; -import org.javamoney.moneta.format.CurrencyStyle; - -public class JavaMoney { - final static Logger LOGGER = Logger.getLogger(JavaMoney.class.getName()); - CurrencyUnit USD; - MonetaryAmount fstAmtUSD; - MonetaryAmount fstAmtEUR; - MonetaryAmount oneDolar; - MonetaryAmount moneyof; - MonetaryAmount fastmoneyof; - MonetaryAmount roundEUR; - MonetaryAmount calcAmtUSD; - MonetaryAmount[] monetaryAmounts; - MonetaryAmount sumAmtCHF; - MonetaryAmount calcMoneyFastMoney; - MonetaryAmount convertedAmountEURtoUSD; - MonetaryAmount convertedAmountEURtoUSD2; - MonetaryAmount convertedAmountUSDtoEUR; - MonetaryAmount convertedAmountUSDtoEUR2; - MonetaryAmount multiplyAmount; - MonetaryAmount divideAmount; - MonetaryAmount oneDivThree; - CurrencyConversion convEUR; - CurrencyConversion convUSD; - CurrencyConversion conversionUSD; - CurrencyConversion conversionEUR; - MonetaryAmount oneEuro; - MonetaryAmountFormat formatUSD; - MonetaryAmountFormat customFormat; - String usFormatted; - String customFormatted; - - public JavaMoney() { - USD = Monetary.getCurrency("USD"); - fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(USD).setNumber(200.50).create(); - fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); - oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); - moneyof = Money.of(12, USD); - fastmoneyof = FastMoney.of(2, USD); - - LOGGER.info("First Amount in USD : " + fstAmtUSD); - LOGGER.info("First Amount in EUR : " + fstAmtEUR); - LOGGER.info("One Dolar : " + oneDolar); - LOGGER.info("MoneyOf : " + moneyof); - LOGGER.info("FastMoneyOf : " + fastmoneyof); - - try{ - @SuppressWarnings("unused") - CurrencyUnit AAA = Monetary.getCurrency("AAA"); - } catch (UnknownCurrencyException e) { - LOGGER.severe("Unknown Currency"); - } - - roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding()); - - LOGGER.info("Rounded EUR : " + roundEUR); - - calcAmtUSD = Money.of(1, "USD").subtract(fstAmtUSD); - - LOGGER.info("Substracting amounts : " + calcAmtUSD); - - calcMoneyFastMoney = moneyof.subtract(fastmoneyof); - - LOGGER.info("Money & FastMoney operations : " + calcMoneyFastMoney); - - monetaryAmounts = - new MonetaryAmount[] { - Money.of(100, "CHF"), - Money.of(10.20, "CHF"), - Money.of(1.15, "CHF"), }; - sumAmtCHF = Money.of(0, "CHF"); - for (MonetaryAmount monetaryAmount : monetaryAmounts) { - sumAmtCHF = sumAmtCHF.add(monetaryAmount); - } - - LOGGER.info("Adding amounts : " + sumAmtCHF); - - multiplyAmount = oneDolar.multiply(0.25); - LOGGER.info("Multiply Amount : " + multiplyAmount); - - divideAmount = oneDolar.divide(0.25); - LOGGER.info("Divide Amount : " + divideAmount); - - try{ - oneDivThree = oneDolar.divide(3); - }catch (ArithmeticException e) { - LOGGER.severe("One divide by Three is an infinite number"); - } - - convEUR = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency("EUR").build()); - convUSD = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency(USD).build()); - - conversionUSD = MonetaryConversions.getConversion("USD"); - conversionEUR = MonetaryConversions.getConversion("EUR"); - - convertedAmountEURtoUSD = fstAmtEUR.with(conversionUSD); - convertedAmountEURtoUSD2 = fstAmtEUR.with(convUSD); - convertedAmountUSDtoEUR = oneDolar.with(conversionEUR); - convertedAmountUSDtoEUR2 = oneDolar.with(convEUR); - LOGGER.info("C1 - " + convertedAmountEURtoUSD); - LOGGER.info("C2 - " + convertedAmountEURtoUSD2); - LOGGER.info("One Euro -> " + convertedAmountUSDtoEUR); - LOGGER.info("One Euro2 -> " + convertedAmountUSDtoEUR2); - - oneEuro = Money.of(1, "EUR"); - - if (oneEuro.equals(FastMoney.of(1, "EUR"))) { - LOGGER.info("Money == FastMoney"); - } else { - LOGGER.info("Money != FastMoney"); - } - - if (oneDolar.equals(Money.of(1, "USD"))) { - LOGGER.info("Factory == Money"); - } else { - LOGGER.info("Factory != Money"); - } - - formatUSD = MonetaryFormats.getAmountFormat(Locale.US); - usFormatted = formatUSD.format(oneDolar); - LOGGER.info("One dolar standard formatted : " + usFormatted); - - customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build()); - customFormatted = customFormat.format(oneDolar); - LOGGER.info("One dolar custom formatted : " + customFormatted); - } - - public static void main(String[] args) { - @SuppressWarnings("unused") - JavaMoney java9Money = new JavaMoney(); - } - -} +package com.baeldung.money; + +import java.util.Locale; +import java.util.logging.Logger; + +import javax.money.CurrencyUnit; +import javax.money.Monetary; +import javax.money.MonetaryAmount; +import javax.money.UnknownCurrencyException; +import javax.money.convert.ConversionQueryBuilder; +import javax.money.convert.CurrencyConversion; +import javax.money.convert.MonetaryConversions; +import javax.money.format.AmountFormatQueryBuilder; +import javax.money.format.MonetaryAmountFormat; +import javax.money.format.MonetaryFormats; + +import org.javamoney.moneta.FastMoney; +import org.javamoney.moneta.Money; +import org.javamoney.moneta.format.CurrencyStyle; + +public class JavaMoney { + final static Logger LOGGER = Logger.getLogger(JavaMoney.class.getName()); + CurrencyUnit USD; + MonetaryAmount fstAmtUSD; + MonetaryAmount fstAmtEUR; + MonetaryAmount oneDolar; + MonetaryAmount moneyof; + MonetaryAmount fastmoneyof; + MonetaryAmount roundEUR; + MonetaryAmount calcAmtUSD; + MonetaryAmount[] monetaryAmounts; + MonetaryAmount sumAmtCHF; + MonetaryAmount calcMoneyFastMoney; + MonetaryAmount convertedAmountEURtoUSD; + MonetaryAmount convertedAmountEURtoUSD2; + MonetaryAmount convertedAmountUSDtoEUR; + MonetaryAmount convertedAmountUSDtoEUR2; + MonetaryAmount multiplyAmount; + MonetaryAmount divideAmount; + MonetaryAmount oneDivThree; + CurrencyConversion convEUR; + CurrencyConversion convUSD; + CurrencyConversion conversionUSD; + CurrencyConversion conversionEUR; + MonetaryAmount oneEuro; + MonetaryAmountFormat formatUSD; + MonetaryAmountFormat customFormat; + String usFormatted; + String customFormatted; + + public JavaMoney() { + USD = Monetary.getCurrency("USD"); + fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(USD).setNumber(200.50).create(); + fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + moneyof = Money.of(12, USD); + fastmoneyof = FastMoney.of(2, USD); + + LOGGER.info("First Amount in USD : " + fstAmtUSD); + LOGGER.info("First Amount in EUR : " + fstAmtEUR); + LOGGER.info("One Dolar : " + oneDolar); + LOGGER.info("MoneyOf : " + moneyof); + LOGGER.info("FastMoneyOf : " + fastmoneyof); + + try{ + @SuppressWarnings("unused") + CurrencyUnit AAA = Monetary.getCurrency("AAA"); + } catch (UnknownCurrencyException e) { + LOGGER.severe("Unknown Currency"); + } + + roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding()); + + LOGGER.info("Rounded EUR : " + roundEUR); + + calcAmtUSD = Money.of(1, "USD").subtract(fstAmtUSD); + + LOGGER.info("Substracting amounts : " + calcAmtUSD); + + calcMoneyFastMoney = moneyof.subtract(fastmoneyof); + + LOGGER.info("Money & FastMoney operations : " + calcMoneyFastMoney); + + monetaryAmounts = + new MonetaryAmount[] { + Money.of(100, "CHF"), + Money.of(10.20, "CHF"), + Money.of(1.15, "CHF"), }; + sumAmtCHF = Money.of(0, "CHF"); + for (MonetaryAmount monetaryAmount : monetaryAmounts) { + sumAmtCHF = sumAmtCHF.add(monetaryAmount); + } + + LOGGER.info("Adding amounts : " + sumAmtCHF); + + multiplyAmount = oneDolar.multiply(0.25); + LOGGER.info("Multiply Amount : " + multiplyAmount); + + divideAmount = oneDolar.divide(0.25); + LOGGER.info("Divide Amount : " + divideAmount); + + try{ + oneDivThree = oneDolar.divide(3); + }catch (ArithmeticException e) { + LOGGER.severe("One divide by Three is an infinite number"); + } + + convEUR = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency("EUR").build()); + convUSD = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency(USD).build()); + + conversionUSD = MonetaryConversions.getConversion("USD"); + conversionEUR = MonetaryConversions.getConversion("EUR"); + + convertedAmountEURtoUSD = fstAmtEUR.with(conversionUSD); + convertedAmountEURtoUSD2 = fstAmtEUR.with(convUSD); + convertedAmountUSDtoEUR = oneDolar.with(conversionEUR); + convertedAmountUSDtoEUR2 = oneDolar.with(convEUR); + LOGGER.info("C1 - " + convertedAmountEURtoUSD); + LOGGER.info("C2 - " + convertedAmountEURtoUSD2); + LOGGER.info("One Euro -> " + convertedAmountUSDtoEUR); + LOGGER.info("One Euro2 -> " + convertedAmountUSDtoEUR2); + + oneEuro = Money.of(1, "EUR"); + + if (oneEuro.equals(FastMoney.of(1, "EUR"))) { + LOGGER.info("Money == FastMoney"); + } else { + LOGGER.info("Money != FastMoney"); + } + + if (oneDolar.equals(Money.of(1, "USD"))) { + LOGGER.info("Factory == Money"); + } else { + LOGGER.info("Factory != Money"); + } + + formatUSD = MonetaryFormats.getAmountFormat(Locale.US); + usFormatted = formatUSD.format(oneDolar); + LOGGER.info("One dolar standard formatted : " + usFormatted); + + customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build()); + customFormatted = customFormat.format(oneDolar); + LOGGER.info("One dolar custom formatted : " + customFormatted); + } + + public static void main(String[] args) { + @SuppressWarnings("unused") + JavaMoney java9Money = new JavaMoney(); + } + +} diff --git a/core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java b/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java similarity index 100% rename from core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java rename to core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationAgent.java diff --git a/core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java b/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java rename to core-java-modules/core-java/src/main/java/com/baeldung/objectsize/InstrumentationExample.java diff --git a/core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF b/core-java-modules/core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF similarity index 100% rename from core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF rename to core-java-modules/core-java/src/main/java/com/baeldung/objectsize/MANIFEST.MF diff --git a/core-java/src/main/java/com/baeldung/printf/PrintfExamples.java b/core-java-modules/core-java/src/main/java/com/baeldung/printf/PrintfExamples.java similarity index 100% rename from core-java/src/main/java/com/baeldung/printf/PrintfExamples.java rename to core-java-modules/core-java/src/main/java/com/baeldung/printf/PrintfExamples.java diff --git a/core-java/src/main/java/com/baeldung/printscreen/README.md b/core-java-modules/core-java/src/main/java/com/baeldung/printscreen/README.md similarity index 100% rename from core-java/src/main/java/com/baeldung/printscreen/README.md rename to core-java-modules/core-java/src/main/java/com/baeldung/printscreen/README.md diff --git a/core-java/src/main/java/com/baeldung/printscreen/Screenshot.java b/core-java-modules/core-java/src/main/java/com/baeldung/printscreen/Screenshot.java similarity index 100% rename from core-java/src/main/java/com/baeldung/printscreen/Screenshot.java rename to core-java-modules/core-java/src/main/java/com/baeldung/printscreen/Screenshot.java diff --git a/core-java/src/main/java/com/baeldung/reflection/BaeldungReflectionUtils.java b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/BaeldungReflectionUtils.java similarity index 100% rename from core-java/src/main/java/com/baeldung/reflection/BaeldungReflectionUtils.java rename to core-java-modules/core-java/src/main/java/com/baeldung/reflection/BaeldungReflectionUtils.java diff --git a/core-java/src/main/java/com/baeldung/reflection/Customer.java b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Customer.java similarity index 100% rename from core-java/src/main/java/com/baeldung/reflection/Customer.java rename to core-java-modules/core-java/src/main/java/com/baeldung/reflection/Customer.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Employee.java b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Employee.java new file mode 100644 index 0000000000..833cf26b14 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Employee.java @@ -0,0 +1,7 @@ +package com.baeldung.reflection; + +public class Employee extends Person { + + public int employeeId; + +} diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java new file mode 100644 index 0000000000..df2a19bbff --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java @@ -0,0 +1,7 @@ +package com.baeldung.reflection; + +public class MonthEmployee extends Employee { + + protected double reward; + +} diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Person.java b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Person.java new file mode 100644 index 0000000000..e036ab5223 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/reflection/Person.java @@ -0,0 +1,8 @@ +package com.baeldung.reflection; + +public class Person { + + protected String lastName; + private String firstName; + +} diff --git a/core-java/src/main/java/com/baeldung/resourcebundle/ExampleControl.java b/core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleControl.java similarity index 100% rename from core-java/src/main/java/com/baeldung/resourcebundle/ExampleControl.java rename to core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleControl.java diff --git a/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource.java b/core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource.java similarity index 100% rename from core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource.java rename to core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource.java diff --git a/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl.java b/core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl.java similarity index 100% rename from core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl.java rename to core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl.java diff --git a/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl_PL.java b/core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl_PL.java similarity index 100% rename from core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl_PL.java rename to core-java-modules/core-java/src/main/java/com/baeldung/resourcebundle/ExampleResource_pl_PL.java diff --git a/core-java/src/main/java/com/baeldung/serialization/Address.java b/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Address.java similarity index 100% rename from core-java/src/main/java/com/baeldung/serialization/Address.java rename to core-java-modules/core-java/src/main/java/com/baeldung/serialization/Address.java diff --git a/core-java/src/main/java/com/baeldung/serialization/Employee.java b/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Employee.java similarity index 100% rename from core-java/src/main/java/com/baeldung/serialization/Employee.java rename to core-java-modules/core-java/src/main/java/com/baeldung/serialization/Employee.java diff --git a/core-java/src/main/java/com/baeldung/serialization/Person.java b/core-java-modules/core-java/src/main/java/com/baeldung/serialization/Person.java similarity index 100% rename from core-java/src/main/java/com/baeldung/serialization/Person.java rename to core-java-modules/core-java/src/main/java/com/baeldung/serialization/Person.java diff --git a/core-java/src/main/java/com/baeldung/staticclass/Pizza.java b/core-java-modules/core-java/src/main/java/com/baeldung/staticclass/Pizza.java similarity index 100% rename from core-java/src/main/java/com/baeldung/staticclass/Pizza.java rename to core-java-modules/core-java/src/main/java/com/baeldung/staticclass/Pizza.java diff --git a/core-java/src/main/java/com/baeldung/system/DetectOS.java b/core-java-modules/core-java/src/main/java/com/baeldung/system/DetectOS.java similarity index 100% rename from core-java/src/main/java/com/baeldung/system/DetectOS.java rename to core-java-modules/core-java/src/main/java/com/baeldung/system/DetectOS.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java b/core-java-modules/core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java new file mode 100644 index 0000000000..38b4a0411d --- /dev/null +++ b/core-java-modules/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()); + } + } + +} diff --git a/core-java/src/main/java/com/baeldung/util/PropertiesLoader.java b/core-java-modules/core-java/src/main/java/com/baeldung/util/PropertiesLoader.java similarity index 100% rename from core-java/src/main/java/com/baeldung/util/PropertiesLoader.java rename to core-java-modules/core-java/src/main/java/com/baeldung/util/PropertiesLoader.java diff --git a/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java similarity index 100% rename from core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java rename to core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java diff --git a/core-java/src/main/java/javac-args/arguments b/core-java-modules/core-java/src/main/java/javac-args/arguments similarity index 100% rename from core-java/src/main/java/javac-args/arguments rename to core-java-modules/core-java/src/main/java/javac-args/arguments diff --git a/core-java/src/main/java/javac-args/options b/core-java-modules/core-java/src/main/java/javac-args/options similarity index 100% rename from core-java/src/main/java/javac-args/options rename to core-java-modules/core-java/src/main/java/javac-args/options diff --git a/core-java/src/main/java/javac-args/types b/core-java-modules/core-java/src/main/java/javac-args/types similarity index 100% rename from core-java/src/main/java/javac-args/types rename to core-java-modules/core-java/src/main/java/javac-args/types diff --git a/core-java/src/main/java/javac-args/xlint-ops b/core-java-modules/core-java/src/main/java/javac-args/xlint-ops similarity index 100% rename from core-java/src/main/java/javac-args/xlint-ops rename to core-java-modules/core-java/src/main/java/javac-args/xlint-ops diff --git a/core-java/src/main/java/log4j.properties b/core-java-modules/core-java/src/main/java/log4j.properties similarity index 100% rename from core-java/src/main/java/log4j.properties rename to core-java-modules/core-java/src/main/java/log4j.properties diff --git a/core-java/src/main/java/org/baeldung/executable/ExecutableMavenJar.java b/core-java-modules/core-java/src/main/java/org/baeldung/executable/ExecutableMavenJar.java similarity index 100% rename from core-java/src/main/java/org/baeldung/executable/ExecutableMavenJar.java rename to core-java-modules/core-java/src/main/java/org/baeldung/executable/ExecutableMavenJar.java diff --git a/core-java/src/main/resources/ESAPI.properties b/core-java-modules/core-java/src/main/resources/ESAPI.properties similarity index 100% rename from core-java/src/main/resources/ESAPI.properties rename to core-java-modules/core-java/src/main/resources/ESAPI.properties diff --git a/core-java/src/test/resources/newFile1.txt b/core-java-modules/core-java/src/main/resources/META-INF/BenchmarkList similarity index 100% rename from core-java/src/test/resources/newFile1.txt rename to core-java-modules/core-java/src/main/resources/META-INF/BenchmarkList diff --git a/core-java/src/main/resources/META-INF/MANIFEST.MF b/core-java-modules/core-java/src/main/resources/META-INF/MANIFEST.MF similarity index 100% rename from core-java/src/main/resources/META-INF/MANIFEST.MF rename to core-java-modules/core-java/src/main/resources/META-INF/MANIFEST.MF diff --git a/core-java/src/main/resources/META-INF/persistence.xml b/core-java-modules/core-java/src/main/resources/META-INF/persistence.xml similarity index 100% rename from core-java/src/main/resources/META-INF/persistence.xml rename to core-java-modules/core-java/src/main/resources/META-INF/persistence.xml diff --git a/core-java/src/main/resources/countries.properties b/core-java-modules/core-java/src/main/resources/countries.properties similarity index 100% rename from core-java/src/main/resources/countries.properties rename to core-java-modules/core-java/src/main/resources/countries.properties diff --git a/core-java/src/main/resources/datasource.properties b/core-java-modules/core-java/src/main/resources/datasource.properties similarity index 100% rename from core-java/src/main/resources/datasource.properties rename to core-java-modules/core-java/src/main/resources/datasource.properties diff --git a/core-java/src/main/resources/files/test.txt b/core-java-modules/core-java/src/main/resources/files/test.txt similarity index 100% rename from core-java/src/main/resources/files/test.txt rename to core-java-modules/core-java/src/main/resources/files/test.txt diff --git a/core-java/src/main/resources/js/bind.js b/core-java-modules/core-java/src/main/resources/js/bind.js similarity index 100% rename from core-java/src/main/resources/js/bind.js rename to core-java-modules/core-java/src/main/resources/js/bind.js diff --git a/core-java/src/main/resources/js/locations.js b/core-java-modules/core-java/src/main/resources/js/locations.js similarity index 100% rename from core-java/src/main/resources/js/locations.js rename to core-java-modules/core-java/src/main/resources/js/locations.js diff --git a/core-java/src/main/resources/js/math_module.js b/core-java-modules/core-java/src/main/resources/js/math_module.js similarity index 100% rename from core-java/src/main/resources/js/math_module.js rename to core-java-modules/core-java/src/main/resources/js/math_module.js diff --git a/core-java/src/main/resources/js/no_such.js b/core-java-modules/core-java/src/main/resources/js/no_such.js similarity index 100% rename from core-java/src/main/resources/js/no_such.js rename to core-java-modules/core-java/src/main/resources/js/no_such.js diff --git a/core-java/src/main/resources/js/script.js b/core-java-modules/core-java/src/main/resources/js/script.js similarity index 100% rename from core-java/src/main/resources/js/script.js rename to core-java-modules/core-java/src/main/resources/js/script.js diff --git a/core-java/src/main/resources/js/trim.js b/core-java-modules/core-java/src/main/resources/js/trim.js similarity index 100% rename from core-java/src/main/resources/js/trim.js rename to core-java-modules/core-java/src/main/resources/js/trim.js diff --git a/core-java/src/main/resources/js/typed_arrays.js b/core-java-modules/core-java/src/main/resources/js/typed_arrays.js similarity index 100% rename from core-java/src/main/resources/js/typed_arrays.js rename to core-java-modules/core-java/src/main/resources/js/typed_arrays.js diff --git a/core-java/src/main/resources/log4j.properties b/core-java-modules/core-java/src/main/resources/log4j.properties similarity index 100% rename from core-java/src/main/resources/log4j.properties rename to core-java-modules/core-java/src/main/resources/log4j.properties diff --git a/core-java/src/main/resources/log4j2.xml b/core-java-modules/core-java/src/main/resources/log4j2.xml similarity index 100% rename from core-java/src/main/resources/log4j2.xml rename to core-java-modules/core-java/src/main/resources/log4j2.xml diff --git a/core-java/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java/src/main/resources/log4jstructuraldp.properties similarity index 100% rename from core-java/src/main/resources/log4jstructuraldp.properties rename to core-java-modules/core-java/src/main/resources/log4jstructuraldp.properties diff --git a/core-java-modules/core-java/src/main/resources/logback.xml b/core-java-modules/core-java/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java/src/test/resources/product.png b/core-java-modules/core-java/src/main/resources/product.png similarity index 100% rename from core-java/src/test/resources/product.png rename to core-java-modules/core-java/src/main/resources/product.png diff --git a/core-java/src/main/resources/resourcebundle/resource.properties b/core-java-modules/core-java/src/main/resources/resourcebundle/resource.properties similarity index 100% rename from core-java/src/main/resources/resourcebundle/resource.properties rename to core-java-modules/core-java/src/main/resources/resourcebundle/resource.properties diff --git a/core-java/src/main/resources/resourcebundle/resource_en.properties b/core-java-modules/core-java/src/main/resources/resourcebundle/resource_en.properties similarity index 100% rename from core-java/src/main/resources/resourcebundle/resource_en.properties rename to core-java-modules/core-java/src/main/resources/resourcebundle/resource_en.properties diff --git a/core-java/src/main/resources/resourcebundle/resource_pl_PL.properties b/core-java-modules/core-java/src/main/resources/resourcebundle/resource_pl_PL.properties similarity index 100% rename from core-java/src/main/resources/resourcebundle/resource_pl_PL.properties rename to core-java-modules/core-java/src/main/resources/resourcebundle/resource_pl_PL.properties diff --git a/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java index 4f0d3a7cd5..45e16f0d25 100644 --- a/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java @@ -1,20 +1,20 @@ -package com.baeldung.abstractclasses.test; - -import com.baeldung.abstractclasses.filereaders.BaseFileReader; -import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - -public class LowercaseFileReaderUnitTest { - - @Test - public void givenLowercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { - Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); - BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); - - assertThat(lowercaseFileReader.readFile()).isInstanceOf(List.class); - } -} +package com.baeldung.abstractclasses.test; + +import com.baeldung.abstractclasses.filereaders.BaseFileReader; +import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class LowercaseFileReaderUnitTest { + + @Test + public void givenLowercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { + Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); + BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); + + assertThat(lowercaseFileReader.readFile()).isInstanceOf(List.class); + } +} diff --git a/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java index e11db57000..dc4df900e4 100644 --- a/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java @@ -1,20 +1,20 @@ -package com.baeldung.abstractclasses.test; - -import com.baeldung.abstractclasses.filereaders.BaseFileReader; -import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; - -public class UppercaseFileReaderUnitTest { - - @Test - public void givenUppercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { - Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); - BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); - - assertThat(uppercaseFileReader.readFile()).isInstanceOf(List.class); - } -} +package com.baeldung.abstractclasses.test; + +import com.baeldung.abstractclasses.filereaders.BaseFileReader; +import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class UppercaseFileReaderUnitTest { + + @Test + public void givenUppercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { + Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); + BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); + + assertThat(uppercaseFileReader.readFile()).isInstanceOf(List.class); + } +} diff --git a/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/asciiart/AsciiArtIntegrationTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java new file mode 100644 index 0000000000..1ca7b7281e --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.bitwiseoperator.test; + +import static org.junit.Assert.assertEquals; +import org.junit.jupiter.api.Test; + +public class BitwiseOperatorUnitTest { + + @Test + public void givenTwoIntegers_whenAndOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 & value2; + assertEquals(4, result); + } + + @Test + public void givenTwoIntegers_whenOrOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 | value2; + assertEquals(7, result); + } + + @Test + public void givenTwoIntegers_whenXorOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 ^ value2; + assertEquals(3, result); + } + + @Test + public void givenOneInteger_whenNotOperator_thenNewDecimalNumber() { + int value1 = 6; + int result = ~value1; + assertEquals(result, -7); + } + + @Test + public void givenOnePositiveInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { + int value = 12; + int rightShift = value >> 2; + assertEquals(3, rightShift); + } + + @Test + public void givenOneNegativeInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { + int value = -12; + int rightShift = value >> 2; + assertEquals(-3, rightShift); + } + + @Test + public void givenOnePositiveInteger_whenLeftShiftOperator_thenNewDecimalNumber() { + int value = 12; + int leftShift = value << 2; + assertEquals(48, leftShift); + } + + @Test + public void givenOneNegativeInteger_whenLeftShiftOperator_thenNewDecimalNumber() { + int value = -12; + int leftShift = value << 2; + assertEquals(-48, leftShift); + } + + @Test + public void givenOnePositiveInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { + int value = 12; + int unsignedRightShift = value >>> 2; + assertEquals(3, unsignedRightShift); + } + + @Test + public void givenOneNegativeInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { + int value = -12; + int unsignedRightShift = value >>> 2; + assertEquals(1073741821, unsignedRightShift); + } + +} diff --git a/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/classloader/PrintClassLoaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/classloader/PrintClassLoaderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/classloader/PrintClassLoaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/classloader/PrintClassLoaderUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java new file mode 100644 index 0000000000..2ec62cbbf9 --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java @@ -0,0 +1,50 @@ +package com.baeldung.curltojava; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.junit.Assert; +import org.junit.Test; + +public class JavaCurlExamplesLiveTest { + + @Test + public void givenCommand_whenCalled_thenProduceZeroExitCode() throws IOException { + String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2"; + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); + processBuilder.directory(new File("/home/")); + Process process = processBuilder.start(); + InputStream inputStream = process.getInputStream(); + // Consume the inputStream so the process can exit + JavaCurlExamples.consumeInputStream(inputStream); + int exitCode = process.exitValue(); + + Assert.assertEquals(0, exitCode); + } + + @Test + public void givenNewCommands_whenCalled_thenCheckIfIsAlive() throws IOException { + String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2"; + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); + processBuilder.directory(new File("/home/")); + Process process = processBuilder.start(); + + // Re-use processBuilder + processBuilder.command(new String[]{"newCommand", "arguments"}); + + Assert.assertEquals(true, process.isAlive()); + } + + @Test + public void whenRequestPost_thenCheckIfReturnContent() throws IOException { + String command = "curl -X POST https://postman-echo.com/post --data foo1=bar1&foo2=bar2"; + Process process = Runtime.getRuntime().exec(command); + + // Get the POST result + String content = JavaCurlExamples.inputStreamToString(process.getInputStream()); + + Assert.assertTrue(null != content && !content.isEmpty()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/encoding/CharacterEncodingExamplesUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/exceptions/GlobalExceptionHandlerUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/fileparser/BufferedReaderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/fileparser/FileReaderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/fileparser/FilesReadAllLinesUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/fileparser/ScannerIntUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/fileparser/ScannerStringUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/graph/GraphTraversalUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/graph/GraphUnitTest.java similarity index 60% rename from core-java/src/test/java/com/baeldung/graph/GraphTraversalUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/graph/GraphUnitTest.java index d955d56d95..68611e508b 100644 --- a/core-java/src/test/java/com/baeldung/graph/GraphTraversalUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/graph/GraphUnitTest.java @@ -1,20 +1,31 @@ package com.baeldung.graph; -import org.junit.Assert; +import static org.junit.Assert.assertEquals; import org.junit.Test; -public class GraphTraversalUnitTest { +public class GraphUnitTest { @Test public void givenAGraph_whenTraversingDepthFirst_thenExpectedResult() { Graph graph = createGraph(); - Assert.assertEquals("[Bob, Rob, Maria, Alice, Mark]", + assertEquals("[Bob, Rob, Maria, Alice, Mark]", GraphTraversal.depthFirstTraversal(graph, "Bob").toString()); } @Test public void givenAGraph_whenTraversingBreadthFirst_thenExpectedResult() { Graph graph = createGraph(); - Assert.assertEquals("[Bob, Alice, Rob, Mark, Maria]", + assertEquals("[Bob, Alice, Rob, Mark, Maria]", + GraphTraversal.breadthFirstTraversal(graph, "Bob").toString()); + } + + @Test + public void givenAGraph_whenRemoveVertex_thenVertedNotFound() { + Graph graph = createGraph(); + assertEquals("[Bob, Alice, Rob, Mark, Maria]", + GraphTraversal.breadthFirstTraversal(graph, "Bob").toString()); + + graph.removeVertex("Maria"); + assertEquals("[Bob, Alice, Rob, Mark]", GraphTraversal.breadthFirstTraversal(graph, "Bob").toString()); } diff --git a/core-java/src/test/java/com/baeldung/grep/GrepWithUnix4JIntegrationTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/grep/GrepWithUnix4JIntegrationTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/grep/GrepWithUnix4JIntegrationTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/grep/GrepWithUnix4JIntegrationTest.java diff --git a/core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/HexToAsciiUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/hexToAscii/README.md b/core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/README.md similarity index 100% rename from core-java/src/test/java/com/baeldung/hexToAscii/README.md rename to core-java-modules/core-java/src/test/java/com/baeldung/hexToAscii/README.md diff --git a/core-java/src/test/java/com/baeldung/java/clock/ClockUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/clock/ClockUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/clock/ClockUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/java/clock/ClockUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/java/currentmethod/CurrentlyExecutedMethodFinderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/properties/PropertiesUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/properties/PropertiesUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/properties/PropertiesUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/java/properties/PropertiesUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/regex/RegexUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/regex/RegexUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/regex/RegexUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/java/regex/RegexUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java8/Java8MapAndFlatMap.java b/core-java-modules/core-java/src/test/java/com/baeldung/java8/Java8MapAndFlatMap.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java8/Java8MapAndFlatMap.java rename to core-java-modules/core-java/src/test/java/com/baeldung/java8/Java8MapAndFlatMap.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/SignInUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/SignInUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/SignInUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/SignInUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/junit4vstestng/SuiteUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java new file mode 100644 index 0000000000..e710eecc66 --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.leapyear; + +import java.time.LocalDate; +import java.time.Year; +import java.time.format.DateTimeFormatter; +import java.util.GregorianCalendar; + +import org.junit.Assert; +import org.junit.Test; + +public class LeapYearUnitTest { + + //Before Java8 + @Test + public void testLeapYearUsingGregorianCalendar () { + Assert.assertFalse(new GregorianCalendar().isLeapYear(2018)); + } + + //Java 8 and above + @Test + public void testLeapYearUsingJavaTimeYear () { + Assert.assertTrue(Year.isLeap(2012)); + } + + @Test + public void testBCYearUsingJavaTimeYear () { + Assert.assertTrue(Year.isLeap(-4)); + } + + @Test + public void testWrongLeapYearUsingJavaTimeYear () { + Assert.assertFalse(Year.isLeap(2018)); + } + + @Test + public void testLeapYearInDateUsingJavaTimeYear () { + LocalDate date = LocalDate.parse("2020-01-05", DateTimeFormatter.ISO_LOCAL_DATE); + Assert.assertTrue(Year.from(date).isLeap()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/manifest/ExecuteJarFileUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/manifest/ExecuteJarFileUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/manifest/ExecuteJarFileUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/manifest/ExecuteJarFileUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/money/JavaMoneyUnitManualTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/money/JavaMoneyUnitManualTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/money/JavaMoneyUnitManualTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/money/JavaMoneyUnitManualTest.java diff --git a/core-java/src/test/java/com/baeldung/printscreen/ScreenshotLiveTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/printscreen/ScreenshotLiveTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/printscreen/ScreenshotLiveTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/printscreen/ScreenshotLiveTest.java diff --git a/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java index 8720aff36b..50daaed950 100644 --- a/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java @@ -1,84 +1,84 @@ -package com.baeldung.properties; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.stream.Stream; - -import org.junit.Test; - -public class MergePropertiesUnitTest { - - @Test - public void givenTwoProperties_whenMergedUsingIteration_thenAllPropertiesInResult() { - Properties globalProperties = mergePropertiesByIteratingKeySet(propertiesA(), propertiesB()); - - testMergedProperties(globalProperties); - } - - @Test - public void givenTwoProperties_whenMergedUsingPutAll_thenAllPropertiesInResult() { - Properties globalProperties = mergePropertiesByUsingPutAll(propertiesA(), propertiesB()); - - testMergedProperties(globalProperties); - } - - @Test - public void givenTwoProperties_whenMergedUsingStreamAPI_thenAllPropertiesInResult() { - Properties globalProperties = mergePropertiesByUsingStreamApi(propertiesB(), propertiesA()); - - testMergedProperties(globalProperties); - } - - private Properties mergePropertiesByIteratingKeySet(Properties... properties) { - Properties mergedProperties = new Properties(); - for (Properties property : properties) { - Set propertyNames = property.stringPropertyNames(); - for (String name : propertyNames) { - String propertyValue = property.getProperty(name); - mergedProperties.setProperty(name, propertyValue); - } - } - return mergedProperties; - } - - private Properties mergePropertiesByUsingPutAll(Properties... properties) { - Properties mergedProperties = new Properties(); - for (Properties property : properties) { - mergedProperties.putAll(property); - } - return mergedProperties; - } - - private Properties mergePropertiesByUsingStreamApi(Properties... properties) { - return Stream.of(properties) - .collect(Properties::new, Map::putAll, Map::putAll); - } - - private Properties propertiesA() { - Properties properties = new Properties(); - properties.setProperty("application.name", "my-app"); - properties.setProperty("application.version", "1.0"); - return properties; - } - - private Properties propertiesB() { - Properties properties = new Properties(); - properties.setProperty("property-1", "sample property"); - properties.setProperty("property-2", "another sample property"); - return properties; - } - - private void testMergedProperties(Properties globalProperties) { - assertThat("There should be 4 properties", globalProperties.size(), equalTo(4)); - assertEquals("Property should be", globalProperties.getProperty("application.name"), "my-app"); - assertEquals("Property should be", globalProperties.getProperty("application.version"), "1.0"); - assertEquals("Property should be", globalProperties.getProperty("property-1"), "sample property"); - assertEquals("Property should be", globalProperties.getProperty("property-2"), "another sample property"); - } - -} +package com.baeldung.properties; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.Test; + +public class MergePropertiesUnitTest { + + @Test + public void givenTwoProperties_whenMergedUsingIteration_thenAllPropertiesInResult() { + Properties globalProperties = mergePropertiesByIteratingKeySet(propertiesA(), propertiesB()); + + testMergedProperties(globalProperties); + } + + @Test + public void givenTwoProperties_whenMergedUsingPutAll_thenAllPropertiesInResult() { + Properties globalProperties = mergePropertiesByUsingPutAll(propertiesA(), propertiesB()); + + testMergedProperties(globalProperties); + } + + @Test + public void givenTwoProperties_whenMergedUsingStreamAPI_thenAllPropertiesInResult() { + Properties globalProperties = mergePropertiesByUsingStreamApi(propertiesB(), propertiesA()); + + testMergedProperties(globalProperties); + } + + private Properties mergePropertiesByIteratingKeySet(Properties... properties) { + Properties mergedProperties = new Properties(); + for (Properties property : properties) { + Set propertyNames = property.stringPropertyNames(); + for (String name : propertyNames) { + String propertyValue = property.getProperty(name); + mergedProperties.setProperty(name, propertyValue); + } + } + return mergedProperties; + } + + private Properties mergePropertiesByUsingPutAll(Properties... properties) { + Properties mergedProperties = new Properties(); + for (Properties property : properties) { + mergedProperties.putAll(property); + } + return mergedProperties; + } + + private Properties mergePropertiesByUsingStreamApi(Properties... properties) { + return Stream.of(properties) + .collect(Properties::new, Map::putAll, Map::putAll); + } + + private Properties propertiesA() { + Properties properties = new Properties(); + properties.setProperty("application.name", "my-app"); + properties.setProperty("application.version", "1.0"); + return properties; + } + + private Properties propertiesB() { + Properties properties = new Properties(); + properties.setProperty("property-1", "sample property"); + properties.setProperty("property-2", "another sample property"); + return properties; + } + + private void testMergedProperties(Properties globalProperties) { + assertThat("There should be 4 properties", globalProperties.size(), equalTo(4)); + assertEquals("Property should be", globalProperties.getProperty("application.name"), "my-app"); + assertEquals("Property should be", globalProperties.getProperty("application.version"), "1.0"); + assertEquals("Property should be", globalProperties.getProperty("property-1"), "sample property"); + assertEquals("Property should be", globalProperties.getProperty("property-2"), "another sample property"); + } + +} diff --git a/core-java/src/test/java/com/baeldung/reflection/BaeldungReflectionUtilsUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/reflection/BaeldungReflectionUtilsUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/reflection/BaeldungReflectionUtilsUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/reflection/BaeldungReflectionUtilsUnitTest.java diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java new file mode 100644 index 0000000000..b1a6a1fe57 --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java @@ -0,0 +1,150 @@ +package com.baeldung.reflection; + +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class PersonAndEmployeeReflectionUnitTest { + + // Fields names + private static final String LAST_NAME_FIELD = "lastName"; + private static final String FIRST_NAME_FIELD = "firstName"; + private static final String EMPLOYEE_ID_FIELD = "employeeId"; + private static final String MONTH_EMPLOYEE_REWARD_FIELD = "reward"; + + @Test + public void givenPersonClass_whenGetDeclaredFields_thenTwoFields() { + // When + Field[] allFields = Person.class.getDeclaredFields(); + + // Then + assertEquals(2, allFields.length); + + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(LAST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(FIRST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + } + + @Test + public void givenEmployeeClass_whenGetDeclaredFields_thenOneField() { + // When + Field[] allFields = Employee.class.getDeclaredFields(); + + // Then + assertEquals(1, allFields.length); + + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(EMPLOYEE_ID_FIELD) + && field.getType().equals(int.class)) + ); + } + + @Test + public void givenEmployeeClass_whenSuperClassGetDeclaredFields_thenOneField() { + // When + Field[] allFields = Employee.class.getSuperclass().getDeclaredFields(); + + // Then + assertEquals(2, allFields.length); + + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(LAST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(FIRST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + } + + @Test + public void givenEmployeeClass_whenGetDeclaredFieldsOnBothClasses_thenThreeFields() { + // When + Field[] personFields = Employee.class.getSuperclass().getDeclaredFields(); + Field[] employeeFields = Employee.class.getDeclaredFields(); + Field[] allFields = new Field[employeeFields.length + personFields.length]; + Arrays.setAll(allFields, i -> (i < personFields.length ? personFields[i] : employeeFields[i - personFields.length])); + + // Then + assertEquals(3, allFields.length); + + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(LAST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(FIRST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + assertTrue(Arrays.stream(allFields).anyMatch(field -> + field.getName().equals(EMPLOYEE_ID_FIELD) + && field.getType().equals(int.class)) + ); + } + + @Test + public void givenEmployeeClass_whenGetDeclaredFieldsOnEmployeeSuperclassWithModifiersFilter_thenOneFields() { + // When + List personFields = Arrays.stream(Employee.class.getSuperclass().getDeclaredFields()) + .filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers())) + .collect(Collectors.toList()); + + // Then + assertEquals(1, personFields.size()); + + assertTrue(personFields.stream().anyMatch(field -> + field.getName().equals(LAST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + } + + @Test + public void givenMonthEmployeeClass_whenGetAllFields_thenThreeFields() { + // When + List allFields = getAllFields(MonthEmployee.class); + + // Then + assertEquals(3, allFields.size()); + + assertTrue(allFields.stream().anyMatch(field -> + field.getName().equals(LAST_NAME_FIELD) + && field.getType().equals(String.class)) + ); + assertTrue(allFields.stream().anyMatch(field -> + field.getName().equals(EMPLOYEE_ID_FIELD) + && field.getType().equals(int.class)) + ); + assertTrue(allFields.stream().anyMatch(field -> + field.getName().equals(MONTH_EMPLOYEE_REWARD_FIELD) + && field.getType().equals(double.class)) + ); + } + + public List getAllFields(Class clazz) { + if (clazz == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(getAllFields(clazz.getSuperclass())); + List filteredFields = Arrays.stream(clazz.getDeclaredFields()) + .filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers())) + .collect(Collectors.toList()); + result.addAll(filteredFields); + return result; + } + +} diff --git a/core-java/src/test/java/com/baeldung/regexp/EscapingCharsUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/regexp/EscapingCharsUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/regexp/EscapingCharsUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/regexp/EscapingCharsUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherManualTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherManualTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherManualTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherManualTest.java diff --git a/core-java/src/test/java/com/baeldung/resourcebundle/ExampleResourceUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/resourcebundle/ExampleResourceUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/resourcebundle/ExampleResourceUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/resourcebundle/ExampleResourceUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/resourcebundle/PropertyResourceUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/resourcebundle/PropertyResourceUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/resourcebundle/PropertyResourceUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/resourcebundle/PropertyResourceUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/scripting/NashornUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/serialization/PersonUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/stack/StackUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/stack/StackUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/stack/StackUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/stack/StackUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/stringisnumeric.zip b/core-java-modules/core-java/src/test/java/com/baeldung/stringisnumeric.zip similarity index 100% rename from core-java/src/test/java/com/baeldung/stringisnumeric.zip rename to core-java-modules/core-java/src/test/java/com/baeldung/stringisnumeric.zip diff --git a/core-java/src/test/java/com/baeldung/system/WhenDetectingOSUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/system/WhenDetectingOSUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/system/WhenDetectingOSUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/system/WhenDetectingOSUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/util/PropertiesLoaderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/util/PropertiesLoaderUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/util/PropertiesLoaderUnitTest.java rename to core-java-modules/core-java/src/test/java/com/baeldung/util/PropertiesLoaderUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/JavaIoUnitTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/JavaIoUnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/JavaIoUnitTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/JavaIoUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/JavaTimerLongRunningUnitTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/JavaTimerLongRunningUnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/JavaTimerLongRunningUnitTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/JavaTimerLongRunningUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/rawtypes/RawTypesUnitTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/rawtypes/RawTypesUnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/rawtypes/RawTypesUnitTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/rawtypes/RawTypesUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/sandbox/SandboxJavaManualTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/sandbox/SandboxJavaManualTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/sandbox/SandboxJavaManualTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/sandbox/SandboxJavaManualTest.java diff --git a/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitIntegrationTest.java b/core-java-modules/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitIntegrationTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitIntegrationTest.java rename to core-java-modules/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitIntegrationTest.java diff --git a/core-java-modules/core-java/src/test/resources/.gitignore b/core-java-modules/core-java/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-modules/core-java/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/core-java/src/test/resources/app.properties b/core-java-modules/core-java/src/test/resources/app.properties similarity index 100% rename from core-java/src/test/resources/app.properties rename to core-java-modules/core-java/src/test/resources/app.properties diff --git a/core-java/src/test/resources/catalog b/core-java-modules/core-java/src/test/resources/catalog similarity index 100% rename from core-java/src/test/resources/catalog rename to core-java-modules/core-java/src/test/resources/catalog diff --git a/core-java/src/test/resources/configuration.properties b/core-java-modules/core-java/src/test/resources/configuration.properties similarity index 100% rename from core-java/src/test/resources/configuration.properties rename to core-java-modules/core-java/src/test/resources/configuration.properties diff --git a/core-java/src/test/resources/default.properties b/core-java-modules/core-java/src/test/resources/default.properties similarity index 100% rename from core-java/src/test/resources/default.properties rename to core-java-modules/core-java/src/test/resources/default.properties diff --git a/core-java/src/test/resources/dictionary.in b/core-java-modules/core-java/src/test/resources/dictionary.in similarity index 100% rename from core-java/src/test/resources/dictionary.in rename to core-java-modules/core-java/src/test/resources/dictionary.in diff --git a/core-java/src/test/resources/encoding.txt b/core-java-modules/core-java/src/test/resources/encoding.txt similarity index 100% rename from core-java/src/test/resources/encoding.txt rename to core-java-modules/core-java/src/test/resources/encoding.txt diff --git a/core-java/src/test/resources/icons.xml b/core-java-modules/core-java/src/test/resources/icons.xml similarity index 100% rename from core-java/src/test/resources/icons.xml rename to core-java-modules/core-java/src/test/resources/icons.xml diff --git a/core-java/src/test/resources/newFile2.txt b/core-java-modules/core-java/src/test/resources/newFile1.txt similarity index 100% rename from core-java/src/test/resources/newFile2.txt rename to core-java-modules/core-java/src/test/resources/newFile1.txt diff --git a/core-java/src/test/resources/newFile3.txt b/core-java-modules/core-java/src/test/resources/newFile2.txt similarity index 100% rename from core-java/src/test/resources/newFile3.txt rename to core-java-modules/core-java/src/test/resources/newFile2.txt diff --git a/core-java/src/test/resources/sourceFile.txt b/core-java-modules/core-java/src/test/resources/newFile3.txt similarity index 100% rename from core-java/src/test/resources/sourceFile.txt rename to core-java-modules/core-java/src/test/resources/newFile3.txt diff --git a/core-java/src/test/resources/original.txt b/core-java-modules/core-java/src/test/resources/original.txt similarity index 56% rename from core-java/src/test/resources/original.txt rename to core-java-modules/core-java/src/test/resources/original.txt index cf8c89d389..8511f56bef 100644 --- a/core-java/src/test/resources/original.txt +++ b/core-java-modules/core-java/src/test/resources/original.txt @@ -1,2 +1,2 @@ -#Copy a File with Java (www.Baeldung.com) +#Copy a File with Java (www.Baeldung.com) Copying Files with Java is Fun! \ No newline at end of file diff --git a/core-java/src/test/resources/sampleNumberFile.txt b/core-java-modules/core-java/src/test/resources/sampleNumberFile.txt similarity index 100% rename from core-java/src/test/resources/sampleNumberFile.txt rename to core-java-modules/core-java/src/test/resources/sampleNumberFile.txt diff --git a/core-java/src/test/resources/sampleTextFile.txt b/core-java-modules/core-java/src/test/resources/sampleTextFile.txt similarity index 100% rename from core-java/src/test/resources/sampleTextFile.txt rename to core-java-modules/core-java/src/test/resources/sampleTextFile.txt diff --git a/persistence-modules/hibernate5/transaction.log b/core-java-modules/core-java/src/test/resources/sourceFile.txt similarity index 100% rename from persistence-modules/hibernate5/transaction.log rename to core-java-modules/core-java/src/test/resources/sourceFile.txt diff --git a/core-java/src/test/resources/test.find b/core-java-modules/core-java/src/test/resources/test.find similarity index 100% rename from core-java/src/test/resources/test.find rename to core-java-modules/core-java/src/test/resources/test.find diff --git a/core-java-modules/core-java/src/test/resources/test_read.in b/core-java-modules/core-java/src/test/resources/test_read.in new file mode 100644 index 0000000000..70c379b63f --- /dev/null +++ b/core-java-modules/core-java/src/test/resources/test_read.in @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/core-java/src/test/resources/test_read1.in b/core-java-modules/core-java/src/test/resources/test_read1.in similarity index 100% rename from core-java/src/test/resources/test_read1.in rename to core-java-modules/core-java/src/test/resources/test_read1.in diff --git a/core-java/src/test/resources/test_read2.in b/core-java-modules/core-java/src/test/resources/test_read2.in similarity index 100% rename from core-java/src/test/resources/test_read2.in rename to core-java-modules/core-java/src/test/resources/test_read2.in diff --git a/core-java/src/test/resources/test_read3.in b/core-java-modules/core-java/src/test/resources/test_read3.in similarity index 100% rename from core-java/src/test/resources/test_read3.in rename to core-java-modules/core-java/src/test/resources/test_read3.in diff --git a/core-java/src/test/resources/test_read4.in b/core-java-modules/core-java/src/test/resources/test_read4.in similarity index 100% rename from core-java/src/test/resources/test_read4.in rename to core-java-modules/core-java/src/test/resources/test_read4.in diff --git a/core-java/src/test/resources/test_read7.in b/core-java-modules/core-java/src/test/resources/test_read7.in similarity index 100% rename from core-java/src/test/resources/test_read7.in rename to core-java-modules/core-java/src/test/resources/test_read7.in diff --git a/core-java/src/test/resources/test_read8.in b/core-java-modules/core-java/src/test/resources/test_read8.in similarity index 100% rename from core-java/src/test/resources/test_read8.in rename to core-java-modules/core-java/src/test/resources/test_read8.in diff --git a/core-java/src/test/resources/test_read_d.in b/core-java-modules/core-java/src/test/resources/test_read_d.in similarity index 100% rename from core-java/src/test/resources/test_read_d.in rename to core-java-modules/core-java/src/test/resources/test_read_d.in diff --git a/core-java/src/test/resources/test_read_multiple.in b/core-java-modules/core-java/src/test/resources/test_read_multiple.in similarity index 100% rename from core-java/src/test/resources/test_read_multiple.in rename to core-java-modules/core-java/src/test/resources/test_read_multiple.in diff --git a/core-java/yofile.txt b/core-java-modules/core-java/yofile.txt similarity index 100% rename from core-java/yofile.txt rename to core-java-modules/core-java/yofile.txt diff --git a/core-java/yofile2.txt b/core-java-modules/core-java/yofile2.txt similarity index 100% rename from core-java/yofile2.txt rename to core-java-modules/core-java/yofile2.txt diff --git a/core-java-modules/multimodulemavenproject/daomodule/pom.xml b/core-java-modules/multimodulemavenproject/daomodule/pom.xml new file mode 100644 index 0000000000..a260e15e6d --- /dev/null +++ b/core-java-modules/multimodulemavenproject/daomodule/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + com.baeldung.multimodulemavenproject + multimodulemavenproject + 1.0 + + com.baeldung.daomodule + daomodule + 1.0 + jar + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + 9 + 9 + + \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/daomodule/src/main/java/com/baeldung/daomodule/Dao.java b/core-java-modules/multimodulemavenproject/daomodule/src/main/java/com/baeldung/daomodule/Dao.java new file mode 100644 index 0000000000..9568bae9d9 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/daomodule/src/main/java/com/baeldung/daomodule/Dao.java @@ -0,0 +1,11 @@ +package com.baeldung.daomodule; +import java.util.List; +import java.util.Optional; + +public interface Dao { + + Optional findById(int id); + + List findAll(); + +} diff --git a/core-java-modules/multimodulemavenproject/daomodule/src/main/java/module-info.java b/core-java-modules/multimodulemavenproject/daomodule/src/main/java/module-info.java new file mode 100644 index 0000000000..20c51d316a --- /dev/null +++ b/core-java-modules/multimodulemavenproject/daomodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.daomodule { + exports com.baeldung.daomodule; +} diff --git a/core-java-modules/multimodulemavenproject/entitymodule/pom.xml b/core-java-modules/multimodulemavenproject/entitymodule/pom.xml new file mode 100644 index 0000000000..b90a7ed068 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/entitymodule/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + com.baeldung.entitymodule + entitymodule + 1.0 + jar + + + com.baeldung.multimodulemavenproject + multimodulemavenproject + 1.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + 9 + 9 + + + \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/com/baeldung/entitymodule/User.java b/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/com/baeldung/entitymodule/User.java new file mode 100644 index 0000000000..c025bffd87 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/com/baeldung/entitymodule/User.java @@ -0,0 +1,19 @@ +package com.baeldung.entitymodule; + +public class User { + + private final String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "User{" + "name=" + name + '}'; + } +} \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/module-info.java b/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/module-info.java new file mode 100644 index 0000000000..b2c4553357 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/entitymodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.entitymodule { + exports com.baeldung.entitymodule; +} diff --git a/core-java-modules/multimodulemavenproject/mainappmodule/pom.xml b/core-java-modules/multimodulemavenproject/mainappmodule/pom.xml new file mode 100644 index 0000000000..1f44a1690c --- /dev/null +++ b/core-java-modules/multimodulemavenproject/mainappmodule/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + com.baeldung.mainappmodule + mainappmodule + 1.0 + jar + + + com.baeldung.multimodulemavenproject + multimodulemavenproject + 1.0 + + + + + com.baeldung.entitymodule + entitymodule + 1.0 + + + com.baeldung.daomodule + daomodule + 1.0 + + + com.baeldung.userdaomodule + userdaomodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + 9 + 9 + + \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/com/baeldung/mainappmodule/Application.java b/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/com/baeldung/mainappmodule/Application.java new file mode 100644 index 0000000000..cf0ba1d9bc --- /dev/null +++ b/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/com/baeldung/mainappmodule/Application.java @@ -0,0 +1,19 @@ +package com.baeldung.mainappmodule; + +import com.baeldung.daomodule.Dao; +import com.baeldung.entitymodule.User; +import com.baeldung.userdaomodule.UserDao; +import java.util.HashMap; +import java.util.Map; + +public class Application { + + public static void main(String args[]) { + Map users = new HashMap<>(); + users.put(1, new User("Julie")); + users.put(2, new User("David")); + Dao userDao = new UserDao(users); + userDao.findAll().forEach(System.out::println); + } + +} diff --git a/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/module-info.java b/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/module-info.java new file mode 100644 index 0000000000..dd7620c7bf --- /dev/null +++ b/core-java-modules/multimodulemavenproject/mainappmodule/src/main/java/module-info.java @@ -0,0 +1,8 @@ +module com.baeldung.mainppmodule { + + requires com.baeldung.entitymodule; + requires com.baeldung.daomodule; + requires com.baeldung.userdaomodule; + uses com.baeldung.userdaomodule.UserDao; + +} diff --git a/core-java-modules/multimodulemavenproject/pom.xml b/core-java-modules/multimodulemavenproject/pom.xml new file mode 100644 index 0000000000..ad347a4179 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + com.baeldung.multimodulemavenproject + multimodulemavenproject + 1.0 + pom + multimodulemavenproject + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + + entitymodule + daomodule + userdaomodule + mainappmodule + + + + + + junit + junit + ${junit.version} + test + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + 1.9 + 1.9 + + + + + + + + + UTF-8 + 3.12.2 + + diff --git a/core-java-modules/multimodulemavenproject/userdaomodule/pom.xml b/core-java-modules/multimodulemavenproject/userdaomodule/pom.xml new file mode 100644 index 0000000000..d3543d5864 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/userdaomodule/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + com.baeldung.userdaomodule + userdaomodule + 1.0 + jar + + + com.baeldung.multimodulemavenproject + multimodulemavenproject + 1.0 + + + + + com.baeldung.entitymodule + entitymodule + 1.0 + + + com.baeldung.daomodule + daomodule + 1.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + 9 + 9 + + + \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/com/baeldung/userdaomodule/UserDao.java b/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/com/baeldung/userdaomodule/UserDao.java new file mode 100644 index 0000000000..aba157b431 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/com/baeldung/userdaomodule/UserDao.java @@ -0,0 +1,32 @@ +package com.baeldung.userdaomodule; + +import com.baeldung.daomodule.Dao; +import com.baeldung.entitymodule.User; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class UserDao implements Dao { + + private final Map users; + + public UserDao() { + users = new HashMap<>(); + } + + public UserDao(Map users) { + this.users = users; + } + + @Override + public List findAll() { + return new ArrayList<>(users.values()); + } + + @Override + public Optional findById(int id) { + return Optional.ofNullable(users.get(id)); + } +} \ No newline at end of file diff --git a/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/module-info.java b/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/module-info.java new file mode 100644 index 0000000000..6dd81dabe5 --- /dev/null +++ b/core-java-modules/multimodulemavenproject/userdaomodule/src/main/java/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.userdaomodule { + requires com.baeldung.entitymodule; + requires com.baeldung.daomodule; + provides com.baeldung.daomodule.Dao with com.baeldung.userdaomodule.UserDao; + exports com.baeldung.userdaomodule; +} diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml new file mode 100644 index 0000000000..11a1003460 --- /dev/null +++ b/core-java-modules/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + com.baeldung.core-java-modules + core-java-modules + core-java-modules + pom + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + pre-jpms + core-java-exceptions + core-java-optional + + + diff --git a/core-java-modules/pre-jpms/README.MD b/core-java-modules/pre-jpms/README.MD new file mode 100644 index 0000000000..8c9af82ba5 --- /dev/null +++ b/core-java-modules/pre-jpms/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue) diff --git a/core-java-modules/pre-jpms/pom.xml b/core-java-modules/pre-jpms/pom.xml new file mode 100644 index 0000000000..380d94fbf1 --- /dev/null +++ b/core-java-modules/pre-jpms/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + pre-jpms + 0.0.1-SNAPSHOT + jar + pre-jpms + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + + pre-jpms + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/dependency-jars/ + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.baeldung.prejpms.App + true + dependency-jars/ + + + + + + + + + UTF-8 + + diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java new file mode 100644 index 0000000000..1afaae30e4 --- /dev/null +++ b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java @@ -0,0 +1,77 @@ +package com.baeldung.prejpms; + +import java.io.StringWriter; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.crypto.provider.SunJCE; + +import sun.misc.BASE64Encoder; +import sun.reflect.Reflection; + +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static void main(String[] args) throws Exception { + + getCrytpographyProviderName(); + getCallStackClassNames(); + getXmlFromObject(new Book(100, "Java Modules Architecture")); + getBase64EncodedString("Java"); + } + + private static void getCrytpographyProviderName() { + try { + LOGGER.info("1. JCE Provider Name: {}\n", new SunJCE().getName()); + } catch (Throwable e) { + LOGGER.error(e.toString()); + } + } + + private static void getCallStackClassNames() { + try { + StringBuffer sbStack = new StringBuffer(); + int i = 0; + Class caller = Reflection.getCallerClass(i++); + do { + sbStack.append(i + ".") + .append(caller.getName()) + .append("\n"); + caller = Reflection.getCallerClass(i++); + } while (caller != null); + LOGGER.info("2. Call Stack:\n{}", sbStack); + } catch (Throwable e) { + LOGGER.error(e.toString()); + } + } + + private static void getXmlFromObject(Book book) { + try { + Marshaller marshallerObj = JAXBContext.newInstance(Book.class) + .createMarshaller(); + marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + StringWriter sw = new StringWriter(); + marshallerObj.marshal(book, sw); + LOGGER.info("3. Xml for Book object:\n{}", sw); + } catch (Throwable e) { + LOGGER.error(e.toString()); + } + + } + + private static void getBase64EncodedString(String inputString) { + try { + String encodedString = new BASE64Encoder().encode(inputString.getBytes()); + LOGGER.info("4. Base Encoded String: {}", encodedString); + } catch (Throwable e) { + LOGGER.error(e.toString()); + } + } +} diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java new file mode 100644 index 0000000000..6780c73738 --- /dev/null +++ b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java @@ -0,0 +1,37 @@ +package com.baeldung.prejpms; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "book") +public class Book { + private long id; + private String name; + + public Book() { + } + + public Book(long id, String name) { + this.id = id; + this.name = name; + } + + @XmlAttribute + public void setId(Long id) { + this.id = id; + } + + @XmlElement(name = "title") + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } +} diff --git a/core-java-modules/pre-jpms/src/main/resources/logback.xml b/core-java-modules/pre-jpms/src/main/resources/logback.xml new file mode 100644 index 0000000000..7c5914e58e --- /dev/null +++ b/core-java-modules/pre-jpms/src/main/resources/logback.xml @@ -0,0 +1,10 @@ + + + + [%level] %msg%n + + + + + + \ No newline at end of file diff --git a/core-java-networking/README.md b/core-java-networking/README.md deleted file mode 100644 index 626ea794e6..0000000000 --- a/core-java-networking/README.md +++ /dev/null @@ -1,7 +0,0 @@ -========= - -## Core Java Networking - -### Relevant Articles - -- [Connecting Through Proxy Servers in Core Java](https://www.baeldung.com/java-connect-via-proxy-server) diff --git a/core-java-networking/pom.xml b/core-java-networking/pom.xml deleted file mode 100644 index 178295e1ec..0000000000 --- a/core-java-networking/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - 4.0.0 - core-java-networking - 0.1.0-SNAPSHOT - jar - core-java-networking - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - core-java-networking - - diff --git a/core-java-sun/src/main/java/com/baeldung/README.md b/core-java-sun/src/main/java/com/baeldung/README.md deleted file mode 100644 index 51809b2882..0000000000 --- a/core-java-sun/src/main/java/com/baeldung/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [SHA-256 Hashing in Java](http://www.baeldung.com/sha-256-hashing-java) diff --git a/core-java/README.md b/core-java/README.md deleted file mode 100644 index 20f6ef5ea7..0000000000 --- a/core-java/README.md +++ /dev/null @@ -1,94 +0,0 @@ -========= - -## Core Java Cookbooks and Examples - -### Relevant Articles: -- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) -- [How to Run a Shell Command in Java](http://www.baeldung.com/run-shell-command-in-java) -- [MD5 Hashing in Java](http://www.baeldung.com/java-md5) -- [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) -- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join) -- [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java) -- [A Guide To Java Regular Expressions API](http://www.baeldung.com/regular-expressions-java) -- [Getting Started with Java Properties](http://www.baeldung.com/java-properties) -- [Pattern Search with Grep in Java](http://www.baeldung.com/grep-in-java) -- [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) -- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven) -- [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm) -- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) -- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) -- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) -- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) -- [JVM Log Forging](http://www.baeldung.com/jvm-log-forging) -- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe) -- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) -- [How to Add a Single Element to a Stream](http://www.baeldung.com/java-stream-append-prepend) -- [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability) -- [How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null) -- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method) -- [Converting a Stack Trace to a String in Java](http://www.baeldung.com/java-stacktrace-to-string) -- [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) -- [Broadcasting and Multicasting in Java](http://www.baeldung.com/java-broadcast-multicast) -- [Period and Duration in Java](http://www.baeldung.com/java-period-duration) -- [OutOfMemoryError: GC Overhead Limit Exceeded](http://www.baeldung.com/java-gc-overhead-limit-exceeded) -- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) -- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack) -- [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter) -- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class) -- [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) -- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac) -- [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator) -- [The Trie Data Structure in Java](http://www.baeldung.com/trie-java) -- [Introduction to Javadoc](http://www.baeldung.com/javadoc) -- [Guide to Externalizable Interface in Java](http://www.baeldung.com/java-externalizable) -- [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat) -- [How to Detect the OS Using Java](http://www.baeldung.com/java-detect-os) -- [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) -- [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) -- [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java) -- [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) -- [Class Loaders in Java](http://www.baeldung.com/java-classloaders) -- [Sending Emails with Java](http://www.baeldung.com/java-email) -- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl) -- [Java KeyStore API](http://www.baeldung.com/java-keystore) -- [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) -- [Introduction to Creational Design Patterns](http://www.baeldung.com/creational-design-patterns) -- [Proxy, Decorator, Adapter and Bridge Patterns](http://www.baeldung.com/java-structural-design-patterns) -- [Singletons in Java](http://www.baeldung.com/java-singleton) -- [Flyweight Pattern in Java](http://www.baeldung.com/java-flyweight) -- [The Observer Pattern in Java](http://www.baeldung.com/java-observer-pattern) -- [Service Locator Pattern](http://www.baeldung.com/java-service-locator-pattern) -- [The Thread.join() Method in Java](http://www.baeldung.com/java-thread-join) -- [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class) -- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension) -- [Console I/O in Java](http://www.baeldung.com/java-console-input-output) -- [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) -- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream) -- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) -- [Guide to Java Instrumentation](http://www.baeldung.com/java-instrumentation) -- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) -- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) -- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods) -- [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception) -- [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string) -- [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root) -- [Convert Double to String, Removing Decimal Places](https://www.baeldung.com/java-double-to-string) -- [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture) -- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset) -- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) -- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties) -- [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks) -- [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format) -- [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures) -- [Implementing a Binary Tree in Java](https://www.baeldung.com/java-binary-tree) -- [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order) -- [Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) -- [Abstract Classes in Java](https://www.baeldung.com/java-abstract-class) -- [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding) -- [Calculate the Area of a Circle in Java](https://www.baeldung.com/java-calculate-circle-area) -- [A Guide to the Java Math Class](https://www.baeldung.com/java-lang-math) -- [Graphs in Java](https://www.baeldung.com/java-graphs) diff --git a/core-java/src/main/java/com/baeldung/README.md b/core-java/src/main/java/com/baeldung/README.md deleted file mode 100644 index 51809b2882..0000000000 --- a/core-java/src/main/java/com/baeldung/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [SHA-256 Hashing in Java](http://www.baeldung.com/sha-256-hashing-java) diff --git a/core-java/src/main/java/com/baeldung/networking/README.md b/core-java/src/main/java/com/baeldung/networking/README.md deleted file mode 100644 index b9e827f085..0000000000 --- a/core-java/src/main/java/com/baeldung/networking/README.md +++ /dev/null @@ -1,5 +0,0 @@ -### Relevant Articles: -- [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java) -- [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) -- [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) diff --git a/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java deleted file mode 100644 index d952d2383b..0000000000 --- a/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.baeldung.string; - - -import org.apache.commons.lang3.StringUtils; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class StringReplaceAndRemoveUnitTest { - - - @Test - public void givenTestStrings_whenReplace_thenProcessedString() { - - String master = "Hello World Baeldung!"; - String target = "Baeldung"; - String replacement = "Java"; - String processed = master.replace(target, replacement); - assertTrue(processed.contains(replacement)); - assertFalse(processed.contains(target)); - - } - - @Test - public void givenTestStrings_whenReplaceAll_thenProcessedString() { - - String master2 = "Welcome to Baeldung, Hello World Baeldung"; - String regexTarget= "(Baeldung)$"; - String replacement = "Java"; - String processed2 = master2.replaceAll(regexTarget, replacement); - assertTrue(processed2.endsWith("Java")); - - } - - @Test - public void givenTestStrings_whenStringBuilderMethods_thenProcessedString() { - - String master = "Hello World Baeldung!"; - String target = "Baeldung"; - String replacement = "Java"; - - int startIndex = master.indexOf(target); - int stopIndex = startIndex + target.length(); - - StringBuilder builder = new StringBuilder(master); - - - builder.delete(startIndex, stopIndex); - assertFalse(builder.toString().contains(target)); - - - builder.replace(startIndex, stopIndex, replacement); - assertTrue(builder.toString().contains(replacement)); - - - } - - - @Test - public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() { - - String master = "Hello World Baeldung!"; - String target = "Baeldung"; - String replacement = "Java"; - - String processed = StringUtils.replace(master, target, replacement); - assertTrue(processed.contains(replacement)); - - String master2 = "Hello World Baeldung!"; - String target2 = "baeldung"; - String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement); - assertFalse(processed2.contains(target)); - - } - - - - - - - -} diff --git a/core-kotlin-2/.gitignore b/core-kotlin-2/.gitignore new file mode 100644 index 0000000000..0c017e8f8c --- /dev/null +++ b/core-kotlin-2/.gitignore @@ -0,0 +1,14 @@ +/bin/ + +#ignore gradle +.gradle/ + + +#ignore build and generated files +build/ +node/ +out/ + +#ignore installed node modules and package lock file +node_modules/ +package-lock.json diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md new file mode 100644 index 0000000000..d75dd2208a --- /dev/null +++ b/core-kotlin-2/README.md @@ -0,0 +1,10 @@ +## 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) +- [Creating a Kotlin Range Iterator on a Custom Object](https://www.baeldung.com/kotlin-custom-range-iterator) +- [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) +- [Kotlin Annotations](https://www.baeldung.com/kotlin-annotations) +- [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) +- [Guide to JVM Platform Annotations in Kotlin](https://www.baeldung.com/kotlin-jvm-annotations) diff --git a/core-kotlin-2/build.gradle b/core-kotlin-2/build.gradle new file mode 100644 index 0000000000..1c52172404 --- /dev/null +++ b/core-kotlin-2/build.gradle @@ -0,0 +1,58 @@ + + +group 'com.baeldung.ktor' +version '1.0-SNAPSHOT' + + +buildscript { + ext.kotlin_version = '1.3.30' + + repositories { + mavenCentral() + } + dependencies { + + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'java' +apply plugin: 'kotlin' +apply plugin: 'application' + +mainClassName = 'APIServer.kt' + +sourceCompatibility = 1.8 +compileKotlin { kotlinOptions.jvmTarget = "1.8" } +compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } + +repositories { + mavenCentral() + jcenter() + maven { url "https://dl.bintray.com/kotlin/ktor" } +} +sourceSets { + main{ + kotlin{ + srcDirs 'com/baeldung/ktor' + } + } +} + +test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + } +} + +dependencies { + implementation "ch.qos.logback:logback-classic:1.2.1" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" + testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2' + testImplementation 'junit:junit:4.12' + testImplementation 'org.assertj:assertj-core:3.12.2' + testImplementation 'org.mockito:mockito-core:2.27.0' + testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" + testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:${kotlin_version}" +} diff --git a/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar b/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..5c2d1cf016 Binary files /dev/null and b/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar differ diff --git a/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties b/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..5f1b1201a7 --- /dev/null +++ b/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/core-kotlin-2/gradlew b/core-kotlin-2/gradlew new file mode 100644 index 0000000000..b0d6d0ab5d --- /dev/null +++ b/core-kotlin-2/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or 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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +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 +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +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 + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/core-kotlin-2/gradlew.bat b/core-kotlin-2/gradlew.bat new file mode 100644 index 0000000000..9991c50326 --- /dev/null +++ b/core-kotlin-2/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem 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, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/core-kotlin-2/pom.xml b/core-kotlin-2/pom.xml new file mode 100644 index 0000000000..be2f5fa68f --- /dev/null +++ b/core-kotlin-2/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + core-kotlin-2 + core-kotlin-2 + jar + + + com.baeldung + parent-kotlin + 1.0.0-SNAPSHOT + ../parent-kotlin + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin.version} + test + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + + + 1.3.30 + 5.4.2 + 2.27.0 + 1.9.12 + 3.10.0 + + + diff --git a/core-kotlin-2/resources/logback.xml b/core-kotlin-2/resources/logback.xml new file mode 100644 index 0000000000..9452207268 --- /dev/null +++ b/core-kotlin-2/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/core-kotlin-2/settings.gradle b/core-kotlin-2/settings.gradle new file mode 100644 index 0000000000..c91c993971 --- /dev/null +++ b/core-kotlin-2/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'KtorWithKotlin' + 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/main/kotlin/com/baeldung/jvmannotations/Document.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt new file mode 100644 index 0000000000..55f60bfa81 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt @@ -0,0 +1,11 @@ +package com.baeldung.jvmannotations + +import java.util.* + +interface Document { + + @JvmDefault + fun getTypeDefault() = "document" + + fun getType() = "document" +} diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java new file mode 100644 index 0000000000..feb71772cb --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java @@ -0,0 +1,9 @@ +package com.baeldung.jvmannotations; + +public class HtmlDocument implements Document { + + @Override + public String getType() { + return "HTML"; + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Message.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Message.kt new file mode 100644 index 0000000000..80180bd924 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Message.kt @@ -0,0 +1,66 @@ +@file:JvmName("MessageHelper") +@file:JvmMultifileClass //used +package com.baeldung.jvmannotations + +import java.util.* + +@JvmName("getMyUsername") +fun getMyName() : String { + return "myUserId" +} + +object MessageBroker { + @JvmStatic + var totalMessagesSent = 0 + + const val maxMessageLength = 0 + + @JvmStatic + fun clearAllMessages() { + } + + @JvmStatic + @JvmOverloads + @Throws(Exception::class) + fun findMessages(sender : String, type : String = "text", maxResults : Int = 10) : List { + if(sender.isEmpty()) { + throw Exception() + } + return ArrayList() + } +} + +class Message { + + // this would cause a compilation error since sender is immutable + // @set:JvmName("setSender") + val sender = "myself" + + // this works as name is overridden + @JvmName("getSenderName") + fun getSender() : String = "from:$sender" + + @get:JvmName("getReceiverName") + @set:JvmName("setReceiverName") + var receiver : String = "" + + @get:JvmName("getContent") + @set:JvmName("setContent") + var text = "" + + // generates a warning + @get:JvmName("getId") + private val id = 0 + + @get:JvmName("hasAttachment") + var hasAttachment = true + + var isEncrypted = true + + fun setReceivers(receiverNames : List) { + } + + @JvmName("setReceiverIds") + fun setReceivers(receiverNames : List) { + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt new file mode 100644 index 0000000000..3b19b12e10 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt @@ -0,0 +1,6 @@ +@file:JvmMultifileClass +@file:JvmName("MessageHelper") //applies to all top level functions / variables / constants +package com.baeldung.jvmannotations + +fun convert(message: Message) { +} diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt new file mode 100644 index 0000000000..41cb0df939 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt @@ -0,0 +1,16 @@ +package com.baeldung.jvmannotations + +import java.util.* +class TextDocument : Document { + override fun getType() = "text" + + fun transformList(list : List) : List { + return list.filter { n -> n.toInt() > 1 } + } + + fun transformListInverseWildcards(list : List<@JvmSuppressWildcards Number>) : List<@JvmWildcard Number> { + return list.filter { n -> n.toInt() > 1 } + } + + var list : List<@JvmWildcard Any> = ArrayList() +} diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt new file mode 100644 index 0000000000..00f2582d5f --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt @@ -0,0 +1,5 @@ +package com.baeldung.jvmannotations + +import java.util.* + +class XmlDocument(d : Document) : Document by d diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/range/CharRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CharRange.kt new file mode 100644 index 0000000000..3151674d61 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/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/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/main/kotlin/com/baeldung/range/Filter.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Filter.kt new file mode 100644 index 0000000000..0e611b14cf --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/FirstLast.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/FirstLast.kt new file mode 100644 index 0000000000..b82f5a8b9b --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/OtherRangeFunctions.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt new file mode 100644 index 0000000000..19dcab89b2 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/Range.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Range.kt new file mode 100644 index 0000000000..c313181599 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/ReverseRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/ReverseRange.kt new file mode 100644 index 0000000000..875cf62200 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/Step.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Step.kt new file mode 100644 index 0000000000..b9c5d48588 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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/kotlin/com/baeldung/range/UntilRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/UntilRange.kt new file mode 100644 index 0000000000..2c116a286f --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/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 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/main/resources/logback.xml b/core-kotlin-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-kotlin-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/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..5c2b6ef47f --- /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 ValidationTest { + + @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 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/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 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)) + } + } + +} + diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt new file mode 100644 index 0000000000..2ec5402e5a --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt @@ -0,0 +1,20 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +import com.baeldung.jvmannotations.*; + +class DocumentTest { + + @Test + fun testDefaultMethod() { + + val myDocument = TextDocument() + val myTextDocument = XmlDocument(myDocument) + + assertEquals("text", myDocument.getType()) + assertEquals("text", myTextDocument.getType()) + assertEquals("document", myTextDocument.getTypeDefault()) + } +} \ 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 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..cb3ed98006 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt @@ -0,0 +1,143 @@ +package com.baeldung.scope + +import org.junit.Test +import kotlin.test.assertTrue + + +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 + } + + assertTrue { + numberOfCharacters == 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" + + 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" + + assertTrue { + thisIsNull.equals("default value") + } + } + + @Test + fun shouldInitializeObjectWhenUsingApply() { + val aStudent = Student().apply { + studentId = "1234567" + name = "Mary" + surname = "Smith" + } + + assertTrue { + aStudent.name.equals("Mary") + } + } + + @Test + fun shouldAllowBuilderStyleObjectDesignWhenApplyUsedInClassMethods() { + val teacher = Teacher() + .setId(1000) + .setName("Martha") + .setSurname("Spector") + + assertTrue { + teacher.surname.equals("Spector") + } + } + + @Test + fun shouldAllowSideEffectWhenUsingAlso() { + val restClient = RestClient("http://www.someurl.com") + + val logger = Logger() + + val headers = restClient + .getResponse() + .also { logger.info(it.toString()) } + .headers + + assertTrue { + logger.wasCalled() && headers.headerInfo.equals("some header info") + } + + } + + @Test + fun shouldInitializeFieldWhenAlsoUsed() { + val aStudent = Student().also { it.name = "John"} + + assertTrue { + aStudent.name.equals("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 + } + + assertTrue { + numberOfCharacters == 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" + + 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 diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt new file mode 100644 index 0000000000..a9ddc99992 --- /dev/null +++ b/core-kotlin-2/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 diff --git a/core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt b/core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt new file mode 100644 index 0000000000..45a8dd7e04 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt @@ -0,0 +1,47 @@ +package stringcomparison + +import org.junit.Test +import kotlin.test.assertFalse +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 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 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 diff --git a/core-kotlin-2/src/test/kotlin/voidtypes/VoidTypesUnitTest.kt b/core-kotlin-2/src/test/kotlin/voidtypes/VoidTypesUnitTest.kt new file mode 100644 index 0000000000..468352dbed --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/voidtypes/VoidTypesUnitTest.kt @@ -0,0 +1,63 @@ +package com.baeldung.voidtypes + +import org.junit.jupiter.api.Test +import kotlin.test.assertNull +import kotlin.test.assertTrue + +class VoidTypesUnitTest { + + // Un-commenting below methods will result into compilation error + // as the syntax used is incorrect and is used for explanation in tutorial. + + // fun returnTypeAsVoidAttempt1(): Void { + // println("Trying with Void as return type") + // } + + // fun returnTypeAsVoidAttempt2(): Void { + // println("Trying with Void as return type") + // return null + // } + + fun returnTypeAsVoidSuccess(): Void? { + println("Function can have Void as return type") + return null + } + + fun unitReturnTypeForNonMeaningfulReturns(): Unit { + println("No meaningful return") + } + + fun unitReturnTypeIsImplicit() { + println("Unit Return type is implicit") + } + + fun alwaysThrowException(): Nothing { + throw IllegalArgumentException() + } + + fun invokeANothingOnlyFunction() { + alwaysThrowException() + + var name = "Tom" + } + + @Test + fun givenJavaVoidFunction_thenMappedToKotlinUnit() { + assertTrue(System.out.println() is Unit) + } + + @Test + fun givenVoidReturnType_thenReturnsNullOnly() { + assertNull(returnTypeAsVoidSuccess()) + } + + @Test + fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() { + assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit) + } + + @Test + fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() { + assertTrue(unitReturnTypeIsImplicit() is Unit) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/resources/Kotlin.in b/core-kotlin-2/src/test/resources/Kotlin.in new file mode 100644 index 0000000000..d140d4429e --- /dev/null +++ b/core-kotlin-2/src/test/resources/Kotlin.in @@ -0,0 +1,5 @@ +Hello to Kotlin. Its: +1. Concise +2. Safe +3. Interoperable +4. Tool-friendly \ No newline at end of file diff --git a/core-kotlin-2/src/test/resources/Kotlin.out b/core-kotlin-2/src/test/resources/Kotlin.out new file mode 100644 index 0000000000..63d15d2528 --- /dev/null +++ b/core-kotlin-2/src/test/resources/Kotlin.out @@ -0,0 +1,2 @@ +Kotlin +Concise, Safe, Interoperable, Tool-friendly \ No newline at end of file diff --git a/core-kotlin-io/.gitignore b/core-kotlin-io/.gitignore new file mode 100644 index 0000000000..f521947850 --- /dev/null +++ b/core-kotlin-io/.gitignore @@ -0,0 +1,11 @@ +/bin/ + +#ignore gradle +.gradle/ + + +#ignore build and generated files +build/ +node/ +target/ +out/ diff --git a/core-kotlin-io/README.md b/core-kotlin-io/README.md new file mode 100644 index 0000000000..cb4dac7e4d --- /dev/null +++ b/core-kotlin-io/README.md @@ -0,0 +1,5 @@ +## Relevant articles: + +- [InputStream to String in Kotlin](https://www.baeldung.com/kotlin-inputstream-to-string) +- [Console I/O in Kotlin](https://www.baeldung.com/kotlin-console-io) + diff --git a/core-kotlin-io/pom.xml b/core-kotlin-io/pom.xml new file mode 100644 index 0000000000..a0b688a223 --- /dev/null +++ b/core-kotlin-io/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + core-kotlin-io + core-kotlin-io + jar + + + com.baeldung + parent-kotlin + 1.0.0-SNAPSHOT + ../parent-kotlin + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin.version} + test + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + + + 1.3.30 + 5.4.2 + 2.27.0 + 1.9.12 + 3.10.0 + + + diff --git a/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt b/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt new file mode 100644 index 0000000000..e94a2e84ee --- /dev/null +++ b/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt @@ -0,0 +1,18 @@ +package com.baeldung.inputstream + +import java.io.InputStream + +fun InputStream.readUpToChar(stopChar: Char): String { + val stringBuilder = StringBuilder() + var currentChar = this.read().toChar() + while (currentChar != stopChar) { + stringBuilder.append(currentChar) + currentChar = this.read().toChar() + if (this.available() <= 0) { + stringBuilder.append(currentChar) + break + } + } + return stringBuilder.toString() +} + diff --git a/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt b/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt new file mode 100644 index 0000000000..c73096fce6 --- /dev/null +++ b/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt @@ -0,0 +1,79 @@ +package com.baeldung.console + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Test +import org.mockito.Mockito.`when` +import org.mockito.Mockito.mock +import java.io.BufferedReader +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.Console +import java.io.InputStreamReader +import java.io.PrintStream +import java.util.* + + +class ConsoleIOUnitTest { + + @Test + fun givenText_whenPrint_thenPrintText() { + val expectedTest = "Hello from Kotlin" + val out = ByteArrayOutputStream() + System.setOut(PrintStream(out)) + + print(expectedTest) + out.flush() + val printedText = String(out.toByteArray()) + + assertThat(printedText).isEqualTo(expectedTest) + } + + @Test + fun givenInput_whenRead_thenReadText() { + val expectedTest = "Hello from Kotlin" + val input = ByteArrayInputStream(expectedTest.toByteArray()) + System.setIn(input) + + val readText = readLine() + + assertThat(readText).isEqualTo(expectedTest) + } + + @Test + fun givenInput_whenReadWithScanner_thenReadText() { + val expectedTest = "Hello from Kotlin" + val scanner = Scanner(ByteArrayInputStream(expectedTest.toByteArray())) + + val readText = scanner.nextLine() + + assertThat(readText).isEqualTo(expectedTest) + } + + @Test + fun givenInput_whenReadWithBufferedReader_thenReadText() { + val expectedTest = "Hello from Kotlin" + val reader = BufferedReader(InputStreamReader(ByteArrayInputStream(expectedTest.toByteArray()))) + + val readText = reader.readLine() + + assertThat(readText).isEqualTo(expectedTest) + } + + @Test + fun givenInput_whenReadWithConsole_thenReadText() { + val expectedTest = "Hello from Kotlin" + val console = mock(Console::class.java) + `when`(console.readLine()).thenReturn(expectedTest) + + val readText = console.readLine() + + assertThat(readText).isEqualTo(expectedTest) + } + + @AfterEach + fun resetIO() { + System.setOut(System.out) + System.setIn(System.`in`) + } +} \ No newline at end of file diff --git a/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt new file mode 100644 index 0000000000..d10d23bef0 --- /dev/null +++ b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt @@ -0,0 +1,72 @@ +package com.baeldung.inputstream + +import kotlinx.io.core.use +import org.junit.Test +import java.io.BufferedReader +import java.io.File +import kotlin.test.assertEquals + +class InputStreamToStringTest { + private val fileName = "src/test/resources/inputstream2string.txt" + private val endOfLine = System.lineSeparator() + private val fileFullContent = "Computer programming can be a hassle$endOfLine" + + "It's like trying to take a defended castle" + + @Test + fun whenReadFileWithBufferedReader_thenFullFileContentIsReadAsString() { + val file = File(fileName) + val inputStream = file.inputStream() + val content = inputStream.bufferedReader().use(BufferedReader::readText) + assertEquals(fileFullContent, content) + } + @Test + fun whenReadFileWithBufferedReaderReadText_thenFullFileContentIsReadAsString() { + val file = File(fileName) + val inputStream = file.inputStream() + val reader = BufferedReader(inputStream.reader()) + var content: String + try { + content = reader.readText() + } finally { + reader.close() + } + assertEquals(fileFullContent, content) + } + @Test + fun whenReadFileWithBufferedReaderManually_thenFullFileContentIsReadAsString() { + val file = File(fileName) + val inputStream = file.inputStream() + val reader = BufferedReader(inputStream.reader()) + val content = StringBuilder() + try { + var line = reader.readLine() + while (line != null) { + content.append(line) + line = reader.readLine() + } + } finally { + reader.close() + } + assertEquals(fileFullContent.replace(endOfLine, ""), content.toString()) + + } + + @Test + fun whenReadFileUpToStopChar_thenPartBeforeStopCharIsReadAsString() { + val file = File(fileName) + val inputStream = file.inputStream() + val content = inputStream.use { it.readUpToChar(' ') } + assertEquals("Computer", content) + } + + @Test + fun whenReadFileWithoutContainingStopChar_thenFullFileContentIsReadAsString() { + val file = File(fileName) + val inputStream = file.inputStream() + val content = inputStream.use { it.readUpToChar('-') } + assertEquals(fileFullContent, content) + } + + +} + diff --git a/core-kotlin-io/src/test/resources/inputstream2string.txt b/core-kotlin-io/src/test/resources/inputstream2string.txt new file mode 100644 index 0000000000..40ef9fc5f3 --- /dev/null +++ b/core-kotlin-io/src/test/resources/inputstream2string.txt @@ -0,0 +1,2 @@ +Computer programming can be a hassle +It's like trying to take a defended castle \ No newline at end of file diff --git a/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..ca6ee9cea8 --- /dev/null +++ b/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 828293ec90..3392db9171 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -1,10 +1,10 @@ ## Relevant articles: - [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin) -- [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when) +- [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) @@ -34,7 +34,6 @@ - [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors) - [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) - [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes) -- [Kotlin with Ktor](https://www.baeldung.com/kotlin-ktor) - [Fuel HTTP Library with Kotlin](https://www.baeldung.com/kotlin-fuel) - [Introduction to Kovenant Library for Kotlin](https://www.baeldung.com/kotlin-kovenant) - [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class) @@ -48,3 +47,12 @@ - [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt) - [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree) - [Generate a Random Alphanumeric String in Kotlin](https://www.baeldung.com/kotlin-random-alphanumeric-string) +- [Kotlin Contracts](https://www.baeldung.com/kotlin-contracts) +- [Operator Overloading in Kotlin](https://www.baeldung.com/kotlin-operator-overloading) +- [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) +- [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) diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml index 8b871f28ee..5de986b49e 100644 --- a/core-kotlin/pom.xml +++ b/core-kotlin/pom.xml @@ -64,24 +64,13 @@ nl.komponents.kovenant kovenant - 3.3.0 + ${kovenant.version} pom uy.kohesive.injekt injekt-core - 1.16.1 - - - uy.kohesive.kovert - kovert-vertx - [1.5.0,1.6.0) - - - nl.komponents.kovenant - kovenant - - + ${injekt-core.version} @@ -93,6 +82,8 @@ 3.10.0 1.4.197 1.15.0 + 3.3.0 + 1.16.1 diff --git a/core-kotlin/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt b/core-kotlin/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt new file mode 100644 index 0000000000..ca0b13cdc7 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt @@ -0,0 +1,23 @@ +package com.baeldung.contract + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +@ExperimentalContracts +inline fun myRun(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +@ExperimentalContracts +fun callsInPlace() { + val i: Int + myRun { + i = 1 // Without contract initialization is forbidden due to possible re-assignment + } + println(i) // Without contract variable might be uninitialized +} + diff --git a/core-kotlin/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt b/core-kotlin/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt new file mode 100644 index 0000000000..56f667af82 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt @@ -0,0 +1,43 @@ +package com.baeldung.contract + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +data class Request(val arg: String) + +class Service { + + @ExperimentalContracts + fun process(request: Request?) { + validate(request) + println(request.arg) + } + +} + +@ExperimentalContracts +private fun validate(request: Request?) { + contract { + returns() implies (request != null) + } + if (request == null) { + throw IllegalArgumentException("Undefined request") + } +} + +data class MyEvent(val message: String) + +@ExperimentalContracts +fun processEvent(event: Any?) { + if (isInterested(event)) { + println(event.message) // Compiler makes smart cast here with the help of contract + } +} + +@ExperimentalContracts +fun isInterested(event: Any?): Boolean { + contract { + returns(true) implies (event is MyEvent) + } + return event is MyEvent +} \ No newline at end of file diff --git a/core-kotlin/src/main/kotlin/com/baeldung/filesystem/FileReader.kt b/core-kotlin/src/main/kotlin/com/baeldung/filesystem/FileReader.kt index 8539378c91..886a3fc51e 100644 --- a/core-kotlin/src/main/kotlin/com/baeldung/filesystem/FileReader.kt +++ b/core-kotlin/src/main/kotlin/com/baeldung/filesystem/FileReader.kt @@ -17,4 +17,8 @@ class FileReader { File(fileName).inputStream().readBytes().toString(Charsets.UTF_8) fun readFileDirectlyAsText(fileName: String): String = File(fileName).readText(Charsets.UTF_8) + + fun readFileUsingGetResource(fileName: String) = this::class.java.getResource(fileName).readText(Charsets.UTF_8) + + fun readFileAsLinesUsingGetResourceAsStream(fileName: String) = this::class.java.getResourceAsStream(fileName).bufferedReader().readLines() } \ No newline at end of file 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..20eda4e64f --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt @@ -0,0 +1,87 @@ +package com.baeldung.forEach + + +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") + 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 allStreetsFlatMap() { + + countries.flatMap { it.cities} + .flatMap { it.streets} + .forEach { println(it) } + } + + fun allFlatMapTable() { + + countries.flatMap { it.getCitiesWithCountryName() } + .forEach { println(it) } + } +} + +fun main(args : Array) { + + val world = World() + + world.allCountriesExplicit() + + world.allNested() + + world.allTable() + + world.allStreetsFlatMap() + + world.allFlatMapTable() +} + + diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt new file mode 100644 index 0000000000..ca57b2965e --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt @@ -0,0 +1,9 @@ +@file:JvmName("Strings") +package com.baeldung.kotlin + +fun String.escapeForXml() : String { + return this + .replace("&", "&") + .replace("<", "<") + .replace(">", ">") +} 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/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/main/kotlin/com/baeldung/static/ConsoleUtils.kt b/core-kotlin/src/main/kotlin/com/baeldung/static/ConsoleUtils.kt new file mode 100644 index 0000000000..23c7cfb11a --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/static/ConsoleUtils.kt @@ -0,0 +1,10 @@ +package com.baeldung.static + +class ConsoleUtils { + companion object { + @JvmStatic + fun debug(debugMessage : String) { + println("[DEBUG] $debugMessage") + } + } +} \ No newline at end of file diff --git a/core-kotlin/src/main/kotlin/com/baeldung/static/LoggingUtils.kt b/core-kotlin/src/main/kotlin/com/baeldung/static/LoggingUtils.kt new file mode 100644 index 0000000000..e67addc9ea --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/static/LoggingUtils.kt @@ -0,0 +1,5 @@ +package com.baeldung.static + +fun debug(debugMessage : String) { + println("[DEBUG] $debugMessage") +} \ No newline at end of file diff --git a/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java b/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java new file mode 100644 index 0000000000..c7ef18b879 --- /dev/null +++ b/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.kotlin; + +import kotlin.text.StringsKt; +import org.junit.Assert; +import org.junit.Test; + +import static com.baeldung.kotlin.Strings.*; + + +public class StringUtilUnitTest { + + @Test + public void shouldEscapeXmlTagsInString() { + String xml = "hi"; + + String escapedXml = escapeForXml(xml); + + Assert.assertEquals("<a>hi</a>", escapedXml); + } + + @Test + public void callingBuiltInKotlinExtensionMethod() { + String name = "john"; + + String capitalizedName = StringsKt.capitalize(name); + + Assert.assertEquals("John", capitalizedName); + } + +} diff --git a/core-kotlin/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt index 67795dda14..ad541c446e 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt @@ -48,4 +48,20 @@ internal class FileReaderTest { assertTrue { text.contains("Hello to Kotlin") } } + + @Test + fun whenReadFileAsTextUsingGetResource_thenCorrect() { + val text = fileReader.readFileUsingGetResource("/Kotlin.in") + + assertTrue { text.contains("1. Concise") } + } + + @Test + fun whenReadFileUsingGetResourceAsStream_thenCorrect() { + val lines = fileReader.readFileAsLinesUsingGetResourceAsStream("/Kotlin.in") + + assertTrue { lines.contains("3. Interoperable") } + } + + } \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt index 09ce898860..44c5cd0ece 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt @@ -6,13 +6,6 @@ import org.junit.Test class ExtensionMethods { @Test fun simpleExtensionMethod() { - fun String.escapeForXml() : String { - return this - .replace("&", "&") - .replace("<", "<") - .replace(">", ">") - } - Assert.assertEquals("Nothing", "Nothing".escapeForXml()) Assert.assertEquals("<Tag>", "".escapeForXml()) Assert.assertEquals("a&b", "a&b".escapeForXml()) 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 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 diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/CalculatorTest5.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/CalculatorTest5.kt index 40cd9adc99..daaedca5a3 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/CalculatorTest5.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/CalculatorTest5.kt @@ -7,12 +7,12 @@ class CalculatorTest5 { private val calculator = Calculator() @Test - fun whenAdding1and3_thenAnswerIs4() { + fun `Adding 1 and 3 should be equal to 4`() { Assertions.assertEquals(4, calculator.add(1, 3)) } @Test - fun whenDividingBy0_thenErrorOccurs() { + fun `Dividing by zero should throw the DivideByZeroException`() { val exception = Assertions.assertThrows(DivideByZeroException::class.java) { calculator.divide(5, 0) } @@ -21,7 +21,7 @@ class CalculatorTest5 { } @Test - fun whenSquaringNumbers_thenCorrectAnswerGiven() { + fun `The square of a number should be equal to that number multiplied in itself`() { Assertions.assertAll( Executable { Assertions.assertEquals(1, calculator.square(1)) }, Executable { Assertions.assertEquals(4, calculator.square(2)) }, @@ -76,7 +76,7 @@ class CalculatorTest5 { Tag("logarithms") ) @Test - fun whenIcalculateLog2Of8_thenIget3() { + fun `Log to base 2 of 8 should be equal to 3`() { Assertions.assertEquals(3.0, calculator.log(2, 8)) } } diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/SimpleTest5.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/SimpleTest5.kt index 70d3fb90bf..15ff201430 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/SimpleTest5.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/junit5/SimpleTest5.kt @@ -5,15 +5,16 @@ import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test class SimpleTest5 { + @Test - fun whenEmptyList_thenListIsEmpty() { + fun `isEmpty should return true for empty lists`() { val list = listOf() Assertions.assertTrue(list::isEmpty) } @Test @Disabled - fun when3equals4_thenTestFails() { + fun `3 is equal to 4`() { Assertions.assertEquals(3, 4) { "Three does not equal four" } diff --git a/core-kotlin/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt new file mode 100644 index 0000000000..8abed144eb --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt @@ -0,0 +1,10 @@ +package com.baeldung.static + +import org.junit.Test + +class ConsoleUtilsUnitTest { + @Test + fun givenAStaticMethod_whenCalled_thenNoErrorIsThrown() { + ConsoleUtils.debug("test message") + } +} \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt new file mode 100644 index 0000000000..59587ff009 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt @@ -0,0 +1,10 @@ +package com.baeldung.static + +import org.junit.Test + +class LoggingUtilsUnitTest { + @Test + fun givenAPackageMethod_whenCalled_thenNoErrorIsThrown() { + debug("test message") + } +} \ No newline at end of file diff --git a/couchbase/README.md b/couchbase/README.md index 9b76609593..7a99ce4299 100644 --- a/couchbase/README.md +++ b/couchbase/README.md @@ -3,7 +3,7 @@ ### Relevant Articles: - [Introduction to Couchbase SDK for Java](http://www.baeldung.com/java-couchbase-sdk) - [Using Couchbase in a Spring Application](http://www.baeldung.com/couchbase-sdk-spring) -- [Asynchronous Batch Opereations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) +- [Asynchronous Batch Operations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) - [Querying Couchbase with MapReduce Views](http://www.baeldung.com/couchbase-query-mapreduce-view) - [Querying Couchbase with N1QL](http://www.baeldung.com/n1ql-couchbase) diff --git a/couchbase/pom.xml b/couchbase/pom.xml index 4f0f8787ca..31e6a53388 100644 --- a/couchbase/pom.xml +++ b/couchbase/pom.xml @@ -5,9 +5,9 @@ com.baeldung couchbase 0.1-SNAPSHOT - jar couchbase Couchbase Tutorials + jar com.baeldung @@ -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.1 diff --git a/custom-pmd/pom.xml b/custom-pmd/pom.xml index 0f73282ae3..74e6d9593b 100644 --- a/custom-pmd/pom.xml +++ b/custom-pmd/pom.xml @@ -4,8 +4,8 @@ org.baeldung.pmd custom-pmd 0.0.1 - jar custom-pmd + jar http://maven.apache.org diff --git a/data-structures/README.md b/data-structures/README.md index b3b1196ce0..2d92068390 100644 --- a/data-structures/README.md +++ b/data-structures/README.md @@ -1,4 +1,4 @@ ## Relevant articles: -- [The Trie Data Structure in Java](http://www.baeldung.com/trie-java) -- [Implementing a Binary Tree in Java](http://www.baeldung.com/java-binary-tree) +[The Trie Data Structure in Java](https://www.baeldung.com/trie-java) +[Implementing a Binary Tree in Java](https://www.baeldung.com/java-binary-tree) diff --git a/ddd/README.md b/ddd/README.md index 60f3a43086..6b68fe2205 100644 --- a/ddd/README.md +++ b/ddd/README.md @@ -1,3 +1,5 @@ ### Relevant articles - [Persisting DDD Aggregates](https://www.baeldung.com/spring-persisting-ddd-aggregates) +- [Double Dispatch in DDD](https://www.baeldung.com/ddd-double-dispatch) +- [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd) diff --git a/ddd/pom.xml b/ddd/pom.xml index a61ae24e92..4ac65ea841 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -1,25 +1,19 @@ 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - - com.baeldung.ddd ddd 0.0.1-SNAPSHOT - jar ddd + jar DDD series examples - - 1.0.1 - 2.22.0 - + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -88,4 +82,11 @@ test + + + 1.0.1 + 2.22.0 + 2.0.6.RELEASE + + \ No newline at end of file diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java new file mode 100644 index 0000000000..db673d5d50 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/AmountBasedDiscountPolicy.java @@ -0,0 +1,15 @@ +package com.baeldung.ddd.order.doubledispatch; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; + +public class AmountBasedDiscountPolicy implements DiscountPolicy { + @Override + public double discount(Order order) { + if (order.totalCost() + .isGreaterThan(Money.of(CurrencyUnit.USD, 500.00))) { + return 0.10; + } else + return 0; + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java new file mode 100644 index 0000000000..7e3c5765c6 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/DiscountPolicy.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch; + +public interface DiscountPolicy { + double discount(Order order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java new file mode 100644 index 0000000000..ac7d49fdeb --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/FlatDiscountPolicy.java @@ -0,0 +1,8 @@ +package com.baeldung.ddd.order.doubledispatch; + +public class FlatDiscountPolicy implements DiscountPolicy { + @Override + public double discount(Order order) { + return 0.01; + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java new file mode 100644 index 0000000000..c2f763e14c --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/Order.java @@ -0,0 +1,29 @@ +package com.baeldung.ddd.order.doubledispatch; + +import java.math.RoundingMode; +import java.util.List; + +import org.joda.money.Money; + +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.OrderVisitor; +import com.baeldung.ddd.order.doubledispatch.visitor.Visitable; + +public class Order extends com.baeldung.ddd.order.Order implements Visitable { + public Order(List orderLines) { + super(orderLines); + } + + public Money totalCost(SpecialDiscountPolicy discountPolicy) { + return totalCost().multipliedBy(1 - applyDiscountPolicy(discountPolicy), RoundingMode.HALF_UP); + } + + protected double applyDiscountPolicy(SpecialDiscountPolicy discountPolicy) { + return discountPolicy.discount(this); + } + + @Override + public void accept(OrderVisitor visitor) { + visitor.visit(this); + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java new file mode 100644 index 0000000000..866e0e63c2 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialDiscountPolicy.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch; + +public interface SpecialDiscountPolicy extends DiscountPolicy { + double discount(SpecialOrder order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java new file mode 100644 index 0000000000..1fe629e0ef --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/SpecialOrder.java @@ -0,0 +1,36 @@ +package com.baeldung.ddd.order.doubledispatch; + +import java.util.List; + +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.OrderVisitor; + +public class SpecialOrder extends Order { + + private boolean eligibleForExtraDiscount; + + public SpecialOrder(List orderLines) { + super(orderLines); + this.eligibleForExtraDiscount = false; + } + + public SpecialOrder(List orderLines, boolean eligibleForSpecialDiscount) { + super(orderLines); + this.eligibleForExtraDiscount = eligibleForSpecialDiscount; + } + + public boolean isEligibleForExtraDiscount() { + return eligibleForExtraDiscount; + } + + @Override + protected double applyDiscountPolicy(SpecialDiscountPolicy discountPolicy) { + return discountPolicy.discount(this); + } + + @Override + public void accept(OrderVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java new file mode 100644 index 0000000000..ea23cdaa4b --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/HtmlOrderViewCreator.java @@ -0,0 +1,24 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public class HtmlOrderViewCreator implements OrderVisitor { + + private String html; + + public String getHtml() { + return html; + } + + @Override + public void visit(Order order) { + html = String.format("

Regular order total cost: %s

", order.totalCost()); + } + + @Override + public void visit(SpecialOrder order) { + html = String.format("

Special Order

total cost: %s

", order.totalCost()); + } + +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java new file mode 100644 index 0000000000..00f0740f6e --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/OrderVisitor.java @@ -0,0 +1,9 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public interface OrderVisitor { + void visit(Order order); + void visit(SpecialOrder order); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java new file mode 100644 index 0000000000..1628718d9b --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/order/doubledispatch/visitor/Visitable.java @@ -0,0 +1,5 @@ +package com.baeldung.ddd.order.doubledispatch.visitor; + +public interface Visitable { + void accept(V visitor); +} diff --git a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java index ed11b0dca4..81ae3bbd19 100644 --- a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java +++ b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaOrder.java @@ -92,7 +92,7 @@ class JpaOrder { } void removeLineItem(int line) { - JpaOrderLine removedLine = orderLines.remove(line); + orderLines.remove(line); } void setCurrencyUnit(String currencyUnit) { diff --git a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java index 61e67fa12a..1d2ae5230a 100644 --- a/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java +++ b/ddd/src/main/java/com/baeldung/ddd/order/jpa/JpaProduct.java @@ -15,7 +15,7 @@ class JpaProduct { public JpaProduct(BigDecimal price, String currencyUnit) { super(); this.price = price; - currencyUnit = currencyUnit; + this.currencyUnit = currencyUnit; } @Override diff --git a/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java b/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java new file mode 100644 index 0000000000..2b0e0b1997 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/OrderFixtureUtils.java @@ -0,0 +1,17 @@ +package com.baeldung.ddd.order; + +import java.util.Arrays; +import java.util.List; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; + +public class OrderFixtureUtils { + public static List anyOrderLines() { + return Arrays.asList(new OrderLine(new Product(Money.of(CurrencyUnit.USD, 100)), 1)); + } + + public static List orderLineItemsWorthNDollars(int totalCost) { + return Arrays.asList(new OrderLine(new Product(Money.of(CurrencyUnit.USD, totalCost)), 1)); + } +} 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/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java new file mode 100644 index 0000000000..0ec73415d3 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/DoubleDispatchDiscountPolicyUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.OrderFixtureUtils; + +public class DoubleDispatchDiscountPolicyUnitTest { + // @formatter:off + @DisplayName( + "given regular order with items worth $100 total, " + + "when apply 10% discount policy, " + + "then cost after discount is $90" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + Order order = new Order(OrderFixtureUtils.orderLineItemsWorthNDollars(100)); + SpecialDiscountPolicy discountPolicy = new SpecialDiscountPolicy() { + + @Override + public double discount(Order order) { + return 0.10; + } + + @Override + public double discount(SpecialOrder order) { + return 0; + } + }; + + // when + Money totalCostAfterDiscount = order.totalCost(discountPolicy); + + // then + assertThat(totalCostAfterDiscount).isEqualTo(Money.of(CurrencyUnit.USD, 90)); + } + + // @formatter:off + @DisplayName( + "given special order eligible for extra discount with items worth $100 total, " + + "when apply 20% discount policy for extra discount orders, " + + "then cost after discount is $80" + ) + // @formatter:on + @Test + void test1() throws Exception { + // given + boolean eligibleForExtraDiscount = true; + Order order = new SpecialOrder(OrderFixtureUtils.orderLineItemsWorthNDollars(100), eligibleForExtraDiscount); + SpecialDiscountPolicy discountPolicy = new SpecialDiscountPolicy() { + + @Override + public double discount(Order order) { + return 0; + } + + @Override + public double discount(SpecialOrder order) { + if (order.isEligibleForExtraDiscount()) + return 0.20; + return 0.10; + } + }; + + // when + Money totalCostAfterDiscount = order.totalCost(discountPolicy); + + // then + assertThat(totalCostAfterDiscount).isEqualTo(Money.of(CurrencyUnit.USD, 80.00)); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java new file mode 100644 index 0000000000..e360c1c76a --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/HtmlOrderViewCreatorUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.OrderFixtureUtils; +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.visitor.HtmlOrderViewCreator; + +public class HtmlOrderViewCreatorUnitTest { + // @formatter:off + @DisplayName( + "given collection of regular and special orders, " + + "when create HTML view using visitor for each order, " + + "then the dedicated view is created for each order" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + List anyOrderLines = OrderFixtureUtils.anyOrderLines(); + List orders = Arrays.asList(new Order(anyOrderLines), new SpecialOrder(anyOrderLines)); + HtmlOrderViewCreator htmlOrderViewCreator = new HtmlOrderViewCreator(); + + // when + orders.get(0) + .accept(htmlOrderViewCreator); + String regularOrderHtml = htmlOrderViewCreator.getHtml(); + orders.get(1) + .accept(htmlOrderViewCreator); + String specialOrderHtml = htmlOrderViewCreator.getHtml(); + + // then + assertThat(regularOrderHtml).containsPattern("

Regular order total cost: .*

"); + assertThat(specialOrderHtml).containsPattern("

Special Order

total cost: .*

"); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java new file mode 100644 index 0000000000..3d135e9dbe --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/MethodOverloadExampleUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.doubledispatch.Order; +import com.baeldung.ddd.order.OrderFixtureUtils; +import com.baeldung.ddd.order.OrderLine; +import com.baeldung.ddd.order.doubledispatch.SpecialDiscountPolicy; +import com.baeldung.ddd.order.doubledispatch.SpecialOrder; + +public class MethodOverloadExampleUnitTest { +// @formatter:off +@DisplayName( + "given discount policy accepting special orders, " + + "when apply the policy on special order declared as regular order, " + + "then regular discount method is used" + ) +// @formatter:on + @Test + void test() throws Exception { + // given + SpecialDiscountPolicy specialPolicy = new SpecialDiscountPolicy() { + @Override + public double discount(Order order) { + return 0.01; + } + + @Override + public double discount(SpecialOrder order) { + return 0.10; + } + }; + Order specialOrder = new SpecialOrder(anyOrderLines()); + + // when + double discount = specialPolicy.discount(specialOrder); + + // then + assertThat(discount).isEqualTo(0.01); + } + + private List anyOrderLines() { + return OrderFixtureUtils.anyOrderLines(); + } +} diff --git a/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java new file mode 100644 index 0000000000..82e074d028 --- /dev/null +++ b/ddd/src/test/java/com/baeldung/ddd/order/doubledispatch/SingleDispatchDiscountPolicyUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.ddd.order.doubledispatch; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.baeldung.ddd.order.OrderFixtureUtils; + +public class SingleDispatchDiscountPolicyUnitTest { + // @formatter:off + @DisplayName( + "given two discount policies, " + + "when use these policies, " + + "then single dispatch chooses the implementation based on runtime type" + ) + // @formatter:on + @Test + void test() throws Exception { + // given + DiscountPolicy flatPolicy = new FlatDiscountPolicy(); + DiscountPolicy amountPolicy = new AmountBasedDiscountPolicy(); + Order orderWorth501Dollars = orderWorthNDollars(501); + + // when + double flatDiscount = flatPolicy.discount(orderWorth501Dollars); + double amountDiscount = amountPolicy.discount(orderWorth501Dollars); + + // then + assertThat(flatDiscount).isEqualTo(0.01); + assertThat(amountDiscount).isEqualTo(0.1); + } + + private Order orderWorthNDollars(int totalCost) { + return new Order(OrderFixtureUtils.orderLineItemsWorthNDollars(totalCost)); + } +} 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/deeplearning4j/pom.xml b/deeplearning4j/pom.xml index 38be189bd0..181dbc871c 100644 --- a/deeplearning4j/pom.xml +++ b/deeplearning4j/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung.deeplearning4j deeplearning4j - jar 1.0-SNAPSHOT deeplearning4j + jar com.baeldung diff --git a/disruptor/pom.xml b/disruptor/pom.xml index c26dcc0cd4..296704f546 100644 --- a/disruptor/pom.xml +++ b/disruptor/pom.xml @@ -4,8 +4,8 @@ com.baeldung disruptor 0.1.0-SNAPSHOT - jar disruptor + jar com.baeldung diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000..72d07d6392 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,61 @@ +version: '3' + +services: + +## VOLUME CONTAINER-TO-CONTAINER AND HOST-TO-CONTAINER TEST ## + + volumes-example-service: + image: alpine:latest + container_name: volumes-example-service + volumes: + - /tmp:/my-volumes/host-volume + - /home:/my-volumes/readonly-host-volume:ro + - my-named-global-volume:/my-volumes/named-global-volume + tty: true # Needed to keep the container running + + another-volumes-example-service: + image: alpine:latest + container_name: another-volumes-example-service + volumes: + - my-named-global-volume:/another-path/the-same-named-global-volume + tty: true # Needed to keep the container running + +## NETWORK CONTAINER-TO-CONTAINER TEST ## + + network-example-service: + image: karthequian/helloworld:latest + container_name: network-example-service + networks: + - my-shared-network + + another-service-in-the-same-network: + image: alpine:latest + container_name: another-service-in-the-same-network + networks: + - my-shared-network + + tty: true # Needed to keep the container running + + another-service-in-its-own-network: + image: alpine:latest + container_name: another-service-in-its-own-network + networks: + - my-private-network + tty: true # Needed to keep the container running + +## NETWORK HOST-TO-CONTAINER TEST ## + + network-example-service-available-to-host-on-port-1337: + image: karthequian/helloworld:latest + container_name: network-example-service-available-to-host-on-port-1337 + networks: + - my-shared-network + ports: + - "1337:80" + +volumes: + my-named-global-volume: + +networks: + my-shared-network: {} + my-private-network: {} diff --git a/easy-random/pom.xml b/easy-random/pom.xml new file mode 100644 index 0000000000..61f0ed2cd4 --- /dev/null +++ b/easy-random/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + easy-random + easy-random + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + + org.jeasy + easy-random-core + 4.0.0 + + + + \ No newline at end of file diff --git a/easy-random/src/main/java/org/baeldung/easy/random/model/Department.java b/easy-random/src/main/java/org/baeldung/easy/random/model/Department.java new file mode 100644 index 0000000000..ee4dc82771 --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/model/Department.java @@ -0,0 +1,17 @@ +package org.baeldung.easy.random.model; + +import java.util.StringJoiner; + +public class Department { + private String depName; + + public Department(String depName) { + this.depName = depName; + } + + @Override + public String toString() { + return new StringJoiner(", ", Department.class.getSimpleName() + "[", "]").add("depName='" + depName + "'") + .toString(); + } +} diff --git a/easy-random/src/main/java/org/baeldung/easy/random/model/Employee.java b/easy-random/src/main/java/org/baeldung/easy/random/model/Employee.java new file mode 100644 index 0000000000..ef63642ca2 --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/model/Employee.java @@ -0,0 +1,70 @@ +package org.baeldung.easy.random.model; + +import java.util.*; + +public class Employee { + + private long id; + private String firstName; + private String lastName; + private Department department; + private Collection coworkers; + private Map quarterGrades; + + public Employee(long id, String firstName, String lastName, Department department) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.department = department; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Employee employee = (Employee) o; + return id == employee.id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public long getId() { + return id; + } + + public Department getDepartment() { + return department; + } + + public Collection getCoworkers() { + return Collections.unmodifiableCollection(coworkers); + } + + public Map getQuarterGrades() { + return Collections.unmodifiableMap(quarterGrades); + } + + @Override + public String toString() { + return new StringJoiner(", ", Employee.class.getSimpleName() + "[", "]").add("id=" + id) + .add("firstName='" + firstName + "'") + .add("lastName='" + lastName + "'") + .add("department=" + department) + .add("coworkers size=" + ((coworkers == null) ? 0 : coworkers.size())) + .add("quarterGrades=" + quarterGrades) + .toString(); + } +} diff --git a/easy-random/src/main/java/org/baeldung/easy/random/model/Grade.java b/easy-random/src/main/java/org/baeldung/easy/random/model/Grade.java new file mode 100644 index 0000000000..cb979be3b8 --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/model/Grade.java @@ -0,0 +1,22 @@ +package org.baeldung.easy.random.model; + +import java.util.StringJoiner; + +public class Grade { + + private int grade; + + public Grade(int grade) { + this.grade = grade; + } + + public int getGrade() { + return grade; + } + + @Override + public String toString() { + return new StringJoiner(", ", Grade.class.getSimpleName() + "[", "]").add("grade=" + grade) + .toString(); + } +} diff --git a/easy-random/src/main/java/org/baeldung/easy/random/model/Person.java b/easy-random/src/main/java/org/baeldung/easy/random/model/Person.java new file mode 100644 index 0000000000..c941499993 --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/model/Person.java @@ -0,0 +1,30 @@ +package org.baeldung.easy.random.model; + +import java.util.StringJoiner; + +public class Person { + + private String firstName; + private String lastName; + private Integer age; + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public Integer getAge() { + return age; + } + + @Override + public String toString() { + return new StringJoiner(", ", Person.class.getSimpleName() + "[", "]").add("firstName='" + firstName + "'") + .add("lastName='" + lastName + "'") + .add("age=" + age) + .toString(); + } +} diff --git a/easy-random/src/main/java/org/baeldung/easy/random/model/YearQuarter.java b/easy-random/src/main/java/org/baeldung/easy/random/model/YearQuarter.java new file mode 100644 index 0000000000..c2868f09b8 --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/model/YearQuarter.java @@ -0,0 +1,50 @@ +package org.baeldung.easy.random.model; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.StringJoiner; + +public class YearQuarter { + + private LocalDate startDate; + private LocalDate endDate; + + public YearQuarter(LocalDate startDate) { + this.startDate = startDate; + autoAdjustEndDate(); + } + + private void autoAdjustEndDate() { + endDate = startDate.plusMonths(3L); + } + + public LocalDate getStartDate() { + return startDate; + } + + public LocalDate getEndDate() { + return endDate; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + YearQuarter quarter = (YearQuarter) o; + return Objects.equals(startDate, quarter.startDate) && Objects.equals(endDate, quarter.endDate); + } + + @Override + public int hashCode() { + return Objects.hash(startDate, endDate); + } + + @Override + public String toString() { + return new StringJoiner(", ", YearQuarter.class.getSimpleName() + "[", "]").add("startDate=" + startDate) + .add("endDate=" + endDate) + .toString(); + } +} diff --git a/easy-random/src/main/java/org/baeldung/easy/random/randomizer/YearQuarterRandomizer.java b/easy-random/src/main/java/org/baeldung/easy/random/randomizer/YearQuarterRandomizer.java new file mode 100644 index 0000000000..05232ffcbc --- /dev/null +++ b/easy-random/src/main/java/org/baeldung/easy/random/randomizer/YearQuarterRandomizer.java @@ -0,0 +1,18 @@ +package org.baeldung.easy.random.randomizer; + +import org.baeldung.easy.random.model.YearQuarter; +import org.jeasy.random.api.Randomizer; + +import java.time.LocalDate; +import java.time.Month; + +public class YearQuarterRandomizer implements Randomizer { + + private LocalDate date = LocalDate.of(1990, Month.SEPTEMBER, 25); + + @Override + public YearQuarter getRandomValue() { + date = date.plusMonths(3); + return new YearQuarter(date); + } +} diff --git a/easy-random/src/test/java/org/baeldung/easy/random/EasyRandomUnitTest.java b/easy-random/src/test/java/org/baeldung/easy/random/EasyRandomUnitTest.java new file mode 100644 index 0000000000..9f7a23db66 --- /dev/null +++ b/easy-random/src/test/java/org/baeldung/easy/random/EasyRandomUnitTest.java @@ -0,0 +1,63 @@ +package org.baeldung.easy.random; + +import org.baeldung.easy.random.model.Employee; +import org.baeldung.easy.random.model.Person; +import org.baeldung.easy.random.model.YearQuarter; +import org.baeldung.easy.random.randomizer.YearQuarterRandomizer; +import org.jeasy.random.EasyRandom; +import org.jeasy.random.EasyRandomParameters; +import org.jeasy.random.FieldPredicates; +import org.jeasy.random.TypePredicates; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +class EasyRandomUnitTest { + + @Test + void givenDefaultConfiguration_thenGenerateSingleObject() { + EasyRandom generator = new EasyRandom(); + Person person = generator.nextObject(Person.class); + + assertNotNull(person.getAge()); + assertNotNull(person.getFirstName()); + assertNotNull(person.getLastName()); + } + + @Test + void givenDefaultConfiguration_thenGenerateObjectsList() { + EasyRandom generator = new EasyRandom(); + List persons = generator.objects(Person.class, 5) + .collect(Collectors.toList()); + + assertEquals(5, persons.size()); + } + + @Test + void givenCustomConfiguration_thenGenerateSingleEmployee() { + EasyRandomParameters parameters = new EasyRandomParameters(); + parameters.stringLengthRange(3, 3); + parameters.collectionSizeRange(5, 5); + parameters.excludeField(FieldPredicates.named("lastName").and(FieldPredicates.inClass(Employee.class))); + parameters.excludeType(TypePredicates.inPackage("not.existing.pkg")); + parameters.randomize(YearQuarter.class, new YearQuarterRandomizer()); + + EasyRandom generator = new EasyRandom(parameters); + Employee employee = generator.nextObject(Employee.class); + + assertEquals(3, employee.getFirstName().length()); + assertEquals(5, employee.getCoworkers().size()); + assertEquals(5, employee.getQuarterGrades().size()); + assertNotNull(employee.getDepartment()); + + assertNull(employee.getLastName()); + + for (YearQuarter key : employee.getQuarterGrades().keySet()) { + assertEquals(key.getStartDate(), key.getEndDate().minusMonths(3L)); + } + } + +} diff --git a/ethereum/pom.xml b/ethereum/pom.xml index bd1bacb221..80e1c04676 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -37,17 +37,17 @@ org.springframework spring-core - ${springframework.version} + ${spring.version} org.springframework spring-web - ${springframework.version} + ${spring.version} org.springframework spring-webmvc - ${springframework.version} + ${spring.version} @@ -88,7 +88,7 @@ javax.servlet javax.servlet-api - ${javax-servlet.version} + ${javax.servlet-api.version} javax.servlet.jsp.jstl @@ -98,7 +98,7 @@ javax.servlet.jsp javax.servlet.jsp-api - ${javax-jsp.version} + ${javax.servlet.jsp-api.version} @@ -123,12 +123,12 @@ org.springframework spring-context - ${springframework.version} + ${spring.version} org.springframework spring-test - ${springframework.version} + ${spring.version} test @@ -160,7 +160,7 @@ org.hamcrest hamcrest-library - ${hamcrest.version} + ${org.hamcrest.version} test @@ -208,21 +208,12 @@ UTF-8 - 1.8 8.5.4 1.5.0-RELEASE 3.3.1 - 5.0.5.RELEASE 1.5.6.RELEASE 2.21.0 - 2.5.0 - 1.3 - 2.9.3 - 2.3.1 - 3.1.0 2.4.0 - 1.2 - 4.12 1.2.3 1.7.25 2.0.4.RELEASE diff --git a/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java b/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java index e05517bc79..3238a19ff9 100644 --- a/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java +++ b/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java @@ -32,8 +32,8 @@ public class EthereumRestController { return CompletableFuture.supplyAsync(() -> { try { - CompletableFuture result = web3Service.getBlockNumber(); - responseTransfer.setMessage(result.get().toString()); + EthBlockNumber result = web3Service.getBlockNumber(); + responseTransfer.setMessage(result.toString()); } catch (Exception e) { responseTransfer.setMessage(GENERIC_EXCEPTION); } @@ -51,8 +51,8 @@ public class EthereumRestController { return CompletableFuture.supplyAsync(() -> { try { - CompletableFuture result = web3Service.getEthAccounts(); - responseTransfer.setMessage(result.get().toString()); + EthAccounts result = web3Service.getEthAccounts(); + responseTransfer.setMessage(result.toString()); } catch (Exception e) { responseTransfer.setMessage(GENERIC_EXCEPTION); } @@ -70,8 +70,8 @@ public class EthereumRestController { Instant start = TimeHelper.start(); return CompletableFuture.supplyAsync(() -> { try { - CompletableFuture result = web3Service.getTransactionCount(); - responseTransfer.setMessage(result.get().toString()); + EthGetTransactionCount result = web3Service.getTransactionCount(); + responseTransfer.setMessage(result.toString()); } catch (Exception e) { responseTransfer.setMessage(GENERIC_EXCEPTION); } @@ -88,8 +88,8 @@ public class EthereumRestController { Instant start = TimeHelper.start(); return CompletableFuture.supplyAsync(() -> { try { - CompletableFuture result = web3Service.getEthBalance(); - responseTransfer.setMessage(result.get().toString()); + EthGetBalance result = web3Service.getEthBalance(); + responseTransfer.setMessage(result.toString()); } catch (Exception e) { responseTransfer.setMessage(GENERIC_EXCEPTION); } diff --git a/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java b/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java index c943ee4006..4b7d01e52b 100644 --- a/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java +++ b/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java @@ -47,47 +47,47 @@ public class Web3Service { return "0x" + binary; } - public CompletableFuture getBlockNumber() { + public EthBlockNumber getBlockNumber() { EthBlockNumber result = new EthBlockNumber(); try { result = this.web3j.ethBlockNumber().sendAsync().get(); } catch (Exception ex) { System.out.println(GENERIC_EXCEPTION); } - return CompletableFuture.completedFuture(result); + return result; } - public CompletableFuture getEthAccounts() { + public EthAccounts getEthAccounts() { EthAccounts result = new EthAccounts(); try { result = this.web3j.ethAccounts().sendAsync().get(); } catch (Exception ex) { System.out.println(GENERIC_EXCEPTION); } - return CompletableFuture.completedFuture(result); + return result; } - public CompletableFuture getTransactionCount() { + public EthGetTransactionCount getTransactionCount() { EthGetTransactionCount result = new EthGetTransactionCount(); try { result = this.web3j.ethGetTransactionCount(DEFAULT_ADDRESS, DefaultBlockParameter.valueOf("latest")).sendAsync().get(); } catch (Exception ex) { System.out.println(GENERIC_EXCEPTION); } - return CompletableFuture.completedFuture(result); + return result; } - public CompletableFuture getEthBalance() { + public EthGetBalance getEthBalance() { EthGetBalance result = new EthGetBalance(); try { result = this.web3j.ethGetBalance(DEFAULT_ADDRESS, DefaultBlockParameter.valueOf("latest")).sendAsync().get(); } catch (Exception ex) { System.out.println(GENERIC_EXCEPTION); } - return CompletableFuture.completedFuture(result); + return result; } - public CompletableFuture fromScratchContractExample() { + public String fromScratchContractExample() { String contractAddress = ""; @@ -108,13 +108,13 @@ public class Web3Service { } catch (Exception ex) { System.out.println(PLEASE_SUPPLY_REAL_DATA); - return CompletableFuture.completedFuture(PLEASE_SUPPLY_REAL_DATA); + return PLEASE_SUPPLY_REAL_DATA; } - return CompletableFuture.completedFuture(contractAddress); + return contractAddress; } @Async - public CompletableFuture sendTx() { + public String sendTx() { String transactionHash = ""; try { @@ -135,10 +135,10 @@ public class Web3Service { } catch (Exception ex) { System.out.println(PLEASE_SUPPLY_REAL_DATA); - return CompletableFuture.completedFuture(PLEASE_SUPPLY_REAL_DATA); + return PLEASE_SUPPLY_REAL_DATA; } - return CompletableFuture.completedFuture(transactionHash); + return transactionHash; } } diff --git a/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java b/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java index 382c96e985..ff02659bd5 100644 --- a/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java +++ b/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java @@ -4,8 +4,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.util.concurrent.CompletableFuture; - public class EthereumContractUnitTest { private Web3Service web3Service; @@ -17,14 +15,14 @@ public class EthereumContractUnitTest { @Test public void testContract() { - CompletableFuture result = web3Service.fromScratchContractExample(); - assert (result instanceof CompletableFuture); + String result = web3Service.fromScratchContractExample(); + assert (result instanceof String); } @Test public void sendTx() { - CompletableFuture result = web3Service.sendTx(); - assert (result instanceof CompletableFuture); + String result = web3Service.sendTx(); + assert (result instanceof String); } @After 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/flyway-cdi-extension/pom.xml b/flyway-cdi-extension/pom.xml index dbb32f1e5a..f49a51ea4b 100644 --- a/flyway-cdi-extension/pom.xml +++ b/flyway-cdi-extension/pom.xml @@ -8,44 +8,49 @@ 1.0-SNAPSHOT flyway-cdi-extension - - 1.8 - 1.8 - - javax.enterprise cdi-api - 2.0.SP1 + ${cdi-api.version} org.jboss.weld.se weld-se-core - 3.0.5.Final + ${weld-se-core.version} runtime org.flywaydb flyway-core - 5.1.4 + ${flyway-core.version} org.apache.tomcat tomcat-jdbc - 8.5.33 + ${tomcat-jdbc.version} javax.annotation javax.annotation-api - 1.3.2 + ${javax.annotation-api.version} com.h2database h2 - 1.4.197 + ${h2.version} runtime + + 1.8 + 1.8 + 2.0.SP1 + 3.0.5.Final + 5.1.4 + 8.5.33 + 1.3.2 + 1.4.197 + diff --git a/geotools/pom.xml b/geotools/pom.xml index 3ac8a63564..17beded326 100644 --- a/geotools/pom.xml +++ b/geotools/pom.xml @@ -4,8 +4,8 @@ 4.0.0 geotools 0.0.1-SNAPSHOT - jar geotools + jar http://maven.apache.org @@ -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/google-cloud/pom.xml b/google-cloud/pom.xml index 85f47cc2f5..ec53b78070 100644 --- a/google-cloud/pom.xml +++ b/google-cloud/pom.xml @@ -4,9 +4,9 @@ 4.0.0 google-cloud 0.1-SNAPSHOT - jar google-cloud Google Cloud Tutorials + jar com.baeldung @@ -30,7 +30,6 @@ - 1.16.18 1.16.0 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) diff --git a/google-web-toolkit/pom.xml b/google-web-toolkit/pom.xml index db9ce2eac0..0723cd3be2 100644 --- a/google-web-toolkit/pom.xml +++ b/google-web-toolkit/pom.xml @@ -7,9 +7,9 @@ 4.0.0 com.baeldung google-web-toolkit - war 1.0-SNAPSHOT google-web-toolkit + war com.baeldung @@ -23,7 +23,7 @@ com.google.gwt gwt - 2.8.2 + ${gwt.version} pom import @@ -49,7 +49,7 @@ junit junit - 4.11 + ${junit.version} test @@ -120,6 +120,7 @@ UTF-8 UTF-8 + 2.8.2 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) diff --git a/grpc/pom.xml b/grpc/pom.xml index 725bec3e70..ab550c31d7 100644 --- a/grpc/pom.xml +++ b/grpc/pom.xml @@ -3,8 +3,8 @@ 4.0.0 grpc 0.0.1-SNAPSHOT - jar grpc + jar com.baeldung diff --git a/gson/README.md b/gson/README.md index e1eb155f43..268116a2ac 100644 --- a/gson/README.md +++ b/gson/README.md @@ -9,3 +9,8 @@ - [Exclude Fields from Serialization in Gson](http://www.baeldung.com/gson-exclude-fields-serialization) - [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) +- [Mapping Multiple JSON Fields to a Single 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) + diff --git a/gson/pom.xml b/gson/pom.xml index 8222cb50e1..a21d783c39 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -67,7 +67,6 @@ 3.5 4.1 2.9.6 - 1.16.10 \ No newline at end of file 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..4e717e72c3 --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java @@ -0,0 +1,49 @@ +package org.baeldung.gson.entities; + +import java.util.Objects; + +public class MyClass { + private int id; + private String name; + + public MyClass(int id, String name) { + this.id = id; + this.name = name; + } + + public MyClass() { } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @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/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/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..5b787f1956 --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java @@ -0,0 +1,117 @@ +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.Arrays; +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 = Arrays.asList(new MyClass(1, "name1"), new MyClass(2, "name2")); + + Gson gson = new Gson(); + String jsonString = gson.toJson(list); + 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,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]"; + + Gson gson = new Gson(); + List outputList = gson.fromJson(inputString, ArrayList.class); + + assertEquals(1, outputList.get(0).getId()); + } + + @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 outputList = gson.fromJson(inputString, listOfMyClassObject); + + assertEquals(inputList, outputList); + } + + @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); + assertTrue(outList.get(1) instanceof Cow); + } + + @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, "type") + .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); + assertTrue(outList.get(1) instanceof Cow); + } +} \ 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(); + } +} 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); + } + +} 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/guava-collections-set/.gitignore b/guava-collections-set/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/guava-collections-set/.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/guava-collections-set/README.md b/guava-collections-set/README.md new file mode 100644 index 0000000000..c36d9e0b61 --- /dev/null +++ b/guava-collections-set/README.md @@ -0,0 +1,8 @@ +# Guava + +## Relevant Articles: + +- [Guava – Sets](http://www.baeldung.com/guava-sets) +- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) +- [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) +- [Guide to Guava Multiset](https://www.baeldung.com/guava-multiset) diff --git a/guava-collections-set/pom.xml b/guava-collections-set/pom.xml new file mode 100644 index 0000000000..46dcae492d --- /dev/null +++ b/guava-collections-set/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + com.baeldung + guava-collections-set + 0.1.0-SNAPSHOT + guava-collections-set + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + guava-collections-set + + + + + 27.1-jre + + 3.6.1 + + + diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java similarity index 93% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java index 1d19423f7e..f474fcb17b 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSet.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSet.java @@ -1,14 +1,9 @@ package org.baeldung.guava; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - import com.google.common.base.Function; +import java.util.*; + public class GuavaMapFromSet extends AbstractMap { private class SingleEntry implements Entry { diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java similarity index 99% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java index d80f047f5c..03f2d8f891 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMapFromSetUnitTest.java @@ -1,15 +1,14 @@ package org.baeldung.guava; -import static org.junit.Assert.assertTrue; +import com.google.common.base.Function; +import org.junit.Test; import java.util.Arrays; import java.util.Map; import java.util.Set; import java.util.TreeSet; -import org.junit.Test; - -import com.google.common.base.Function; +import static org.junit.Assert.assertTrue; public class GuavaMapFromSetUnitTest { diff --git a/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java new file mode 100644 index 0000000000..e74db29881 --- /dev/null +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java @@ -0,0 +1,92 @@ +package org.baeldung.guava; + +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class GuavaMultiSetUnitTest { + + @Test + public void givenMultiSet_whenAddingValues_shouldReturnCorrectCount() { + Multiset bookStore = HashMultiset.create(); + bookStore.add("Potter"); + bookStore.add("Potter"); + bookStore.add("Potter"); + + assertThat(bookStore.contains("Potter")).isTrue(); + assertThat(bookStore.count("Potter")).isEqualTo(3); + } + + @Test + public void givenMultiSet_whenRemovingValues_shouldReturnCorrectCount() { + Multiset bookStore = HashMultiset.create(); + bookStore.add("Potter"); + bookStore.add("Potter"); + + bookStore.remove("Potter"); + assertThat(bookStore.contains("Potter")).isTrue(); + assertThat(bookStore.count("Potter")).isEqualTo(1); + } + + @Test + public void givenMultiSet_whenSetCount_shouldReturnCorrectCount() { + Multiset bookStore = HashMultiset.create(); + bookStore.setCount("Potter", 50); + assertThat(bookStore.count("Potter")).isEqualTo(50); + } + + @Test + public void givenMultiSet_whenSettingNegativeCount_shouldThrowException() { + Multiset bookStore = HashMultiset.create(); + assertThatThrownBy(() -> bookStore.setCount("Potter", -1)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void givenMultiSet_whenSettingCountWithEmptySet_shouldBeSuccessful() { + Multiset bookStore = HashMultiset.create(); + assertThat(bookStore.setCount("Potter", 0, 2)).isTrue(); + } + + @Test + public void givenMultiSet_whenSettingCountWithCorrectValue_shouldBeSuccessful() { + Multiset bookStore = HashMultiset.create(); + bookStore.add("Potter"); + bookStore.add("Potter"); + + assertThat(bookStore.setCount("Potter", 2, 52)).isTrue(); + } + + @Test + public void givenMultiSet_whenSettingCountWithIncorrectValue_shouldFail() { + Multiset bookStore = HashMultiset.create(); + bookStore.add("Potter"); + bookStore.add("Potter"); + + assertThat(bookStore.setCount("Potter", 5, 52)).isFalse(); + } + + @Test + public void givenMap_compareMultiSetOperations() { + Map bookStore = new HashMap<>(); + bookStore.put("Potter", 3); + + assertThat(bookStore.containsKey("Potter")).isTrue(); + assertThat(bookStore.get("Potter")).isEqualTo(3); + + bookStore.put("Potter", 2); + assertThat(bookStore.get("Potter")).isEqualTo(2); + + bookStore.put("Potter", null); + assertThat(bookStore.containsKey("Potter")).isTrue(); + + bookStore.put("Potter", -1); + assertThat(bookStore.containsKey("Potter")).isTrue(); + } +} \ No newline at end of file diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java similarity index 97% rename from guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java rename to guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java index 6f3092d845..edefc61fc4 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaRangeSetUnitTest.java @@ -1,13 +1,12 @@ package org.baeldung.guava; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import org.junit.Test; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; +import org.junit.Test; + +import static org.junit.Assert.*; public class GuavaRangeSetUnitTest { @@ -122,6 +121,5 @@ public class GuavaRangeSetUnitTest { .add(Range.closed(0, 2)) .add(Range.closed(3, 5)) .add(Range.closed(5, 8)).build(); - } } diff --git a/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java new file mode 100644 index 0000000000..dfd90ad738 --- /dev/null +++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaSetOperationsUnitTest.java @@ -0,0 +1,131 @@ +package org.baeldung.guava; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class GuavaSetOperationsUnitTest { + + @Test + public void whenCalculatingUnionOfSets_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set union = Sets.union(first, second); + assertThat(union, containsInAnyOrder('a', 'b', 'c', 'd')); + } + + @Test + public void whenCalculatingCartesianProductOfSets_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b'); + final Set second = ImmutableSet.of('c', 'd'); + final Set> result = Sets.cartesianProduct(ImmutableList.of(first, second)); + + final Function, String> func = new Function, String>() { + @Override + public final String apply(final List input) { + return Joiner + .on(" ").join(input); + } + }; + + final Iterable joined = Iterables.transform(result, func); + assertThat(joined, containsInAnyOrder("a c", "a d", "b c", "b d")); + } + + @Test + public void whenCalculatingSetIntersection_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set intersection = Sets.intersection(first, second); + assertThat(intersection, containsInAnyOrder('b', 'c')); + } + + @Test + public void whenCalculatingSetSymmetricDifference_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set intersection = Sets.symmetricDifference(first, second); + assertThat(intersection, containsInAnyOrder('a', 'd')); + } + + @Test + public void whenCalculatingPowerSet_thenCorrect() { + final Set chars = ImmutableSet.of('a', 'b'); + final Set> result = Sets.powerSet(chars); + + final Set empty = ImmutableSet. builder().build(); + final Set a = ImmutableSet.of('a'); + final Set b = ImmutableSet.of('b'); + final Set aB = ImmutableSet.of('a', 'b'); + + assertThat(result, contains(empty, a, b, aB)); + } + + @Test + public void whenCreatingRangeOfIntegersSet_thenCreated() { + final int start = 10; + final int end = 30; + final ContiguousSet set = ContiguousSet.create(Range.closed(start, end), DiscreteDomain.integers()); + + assertEquals(21, set.size()); + assertEquals(10, set.first().intValue()); + assertEquals(30, set.last().intValue()); + } + + @Test + public void whenUsingRangeSet_thenCorrect() { + final RangeSet rangeSet = TreeRangeSet.create(); + rangeSet.add(Range.closed(1, 10)); + rangeSet.add(Range.closed(12, 15)); + + assertEquals(2, rangeSet.asRanges().size()); + + rangeSet.add(Range.closed(10, 12)); + assertTrue(rangeSet.encloses(Range.closed(1, 15))); + assertEquals(1, rangeSet.asRanges().size()); + } + + @Test + public void whenInsertDuplicatesInMultiSet_thenInserted() { + final Multiset names = HashMultiset.create(); + names.add("John"); + names.add("Adam", 3); + names.add("John"); + + assertEquals(2, names.count("John")); + names.remove("John"); + assertEquals(1, names.count("John")); + + assertEquals(3, names.count("Adam")); + names.remove("Adam", 2); + assertEquals(1, names.count("Adam")); + } + + @Test + public void whenGetTopOcurringElementsWithMultiSet_thenCorrect() { + final Multiset names = HashMultiset.create(); + names.add("John"); + names.add("Adam", 5); + names.add("Jane"); + names.add("Tom", 2); + + final Set sorted = Multisets.copyHighestCountFirst(names).elementSet(); + final List topTwo = Lists.newArrayList(sorted).subList(0, 2); + assertEquals(2, topTwo.size()); + assertEquals("Adam", topTwo.get(0)); + assertEquals("Tom", topTwo.get(1)); + } +} diff --git a/guava-collections/README.md b/guava-collections/README.md index fc9cf549c3..e919a98c2b 100644 --- a/guava-collections/README.md +++ b/guava-collections/README.md @@ -11,13 +11,10 @@ - [Filtering and Transforming Collections in Guava](http://www.baeldung.com/guava-filter-and-transform-a-collection) - [Guava – Join and Split Collections](http://www.baeldung.com/guava-joiner-and-splitter-tutorial) - [Guava – Lists](http://www.baeldung.com/guava-lists) -- [Guava – Sets](http://www.baeldung.com/guava-sets) - [Guava – Maps](http://www.baeldung.com/guava-maps) - [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap) -- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) - [Guide to Guava RangeMap](http://www.baeldung.com/guava-rangemap) - [Guide to Guava MinMaxPriorityQueue and EvictingQueue](http://www.baeldung.com/guava-minmax-priority-queue-and-evicting-queue) - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) -- [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) - [Guide to Guava Table](http://www.baeldung.com/guava-table) - [Guide to Guava ClassToInstanceMap](http://www.baeldung.com/guava-class-to-instance-map) \ No newline at end of file diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java b/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java index cb6ec7ef96..ab38afa5c4 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java +++ b/guava-collections/src/test/java/org/baeldung/guava/GuavaCollectionTypesUnitTest.java @@ -111,120 +111,6 @@ public class GuavaCollectionTypesUnitTest { assertThat(immutable, contains("John", "Adam", "Jane", "Tom")); } - // sets - - @Test - public void whenCalculateUnionOfSets_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set union = Sets.union(first, second); - assertThat(union, containsInAnyOrder('a', 'b', 'c', 'd')); - } - - @Test - public void whenCalculateSetsProduct_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b'); - final Set second = ImmutableSet.of('c', 'd'); - final Set> result = Sets.cartesianProduct(ImmutableList.of(first, second)); - - final Function, String> func = new Function, String>() { - @Override - public final String apply(final List input) { - return Joiner.on(" ").join(input); - } - }; - - final Iterable joined = Iterables.transform(result, func); - assertThat(joined, containsInAnyOrder("a c", "a d", "b c", "b d")); - } - - @Test - public void whenCalculatingSetIntersection_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set intersection = Sets.intersection(first, second); - assertThat(intersection, containsInAnyOrder('b', 'c')); - } - - @Test - public void whenCalculatingSetSymmetricDifference_thenCorrect() { - final Set first = ImmutableSet.of('a', 'b', 'c'); - final Set second = ImmutableSet.of('b', 'c', 'd'); - - final Set intersection = Sets.symmetricDifference(first, second); - assertThat(intersection, containsInAnyOrder('a', 'd')); - } - - @Test - public void whenCalculatingPowerSet_thenCorrect() { - final Set chars = ImmutableSet.of('a', 'b'); - final Set> result = Sets.powerSet(chars); - - final Set empty = ImmutableSet. builder().build(); - final Set a = ImmutableSet.of('a'); - final Set b = ImmutableSet.of('b'); - final Set aB = ImmutableSet.of('a', 'b'); - - assertThat(result, contains(empty, a, b, aB)); - } - - @Test - public void whenCreateRangeOfIntegersSet_thenCreated() { - final int start = 10; - final int end = 30; - final ContiguousSet set = ContiguousSet.create(Range.closed(start, end), DiscreteDomain.integers()); - - assertEquals(21, set.size()); - assertEquals(10, set.first().intValue()); - assertEquals(30, set.last().intValue()); - } - - @Test - public void whenCreateRangeSet_thenCreated() { - final RangeSet rangeSet = TreeRangeSet.create(); - rangeSet.add(Range.closed(1, 10)); - rangeSet.add(Range.closed(12, 15)); - - assertEquals(2, rangeSet.asRanges().size()); - - rangeSet.add(Range.closed(10, 12)); - assertTrue(rangeSet.encloses(Range.closed(1, 15))); - assertEquals(1, rangeSet.asRanges().size()); - } - - @Test - public void whenInsertDuplicatesInMultiSet_thenInserted() { - final Multiset names = HashMultiset.create(); - names.add("John"); - names.add("Adam", 3); - names.add("John"); - - assertEquals(2, names.count("John")); - names.remove("John"); - assertEquals(1, names.count("John")); - - assertEquals(3, names.count("Adam")); - names.remove("Adam", 2); - assertEquals(1, names.count("Adam")); - } - - @Test - public void whenGetTopUsingMultiSet_thenCorrect() { - final Multiset names = HashMultiset.create(); - names.add("John"); - names.add("Adam", 5); - names.add("Jane"); - names.add("Tom", 2); - - final Set sorted = Multisets.copyHighestCountFirst(names).elementSet(); - final List topTwo = Lists.newArrayList(sorted).subList(0, 2); - assertEquals(2, topTwo.size()); - assertEquals("Adam", topTwo.get(0)); - assertEquals("Tom", topTwo.get(1)); - } - @Test public void whenCreateImmutableMap_thenCreated() { final Map salary = ImmutableMap. builder().put("John", 1000).put("Jane", 1500).put("Adam", 2000).put("Tom", 2000).build(); 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) diff --git a/guava-modules/guava-21/README.md b/guava-modules/guava-21/README.md index 68c1ac4a8e..4e897325b6 100644 --- a/guava-modules/guava-21/README.md +++ b/guava-modules/guava-21/README.md @@ -1,4 +1,4 @@ ### Relevant articles: -- [New Stream, Comparator and Collector Functionality in Guava 21](http://www.baeldung.com/guava-21-new) +- [New Stream, Comparator and Collector in Guava 21](http://www.baeldung.com/guava-21-new) - [New in Guava 21 common.util.concurrent](http://www.baeldung.com/guava-21-util-concurrent) - [Zipping Collections in Java](http://www.baeldung.com/java-collections-zip) diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml new file mode 100644 index 0000000000..fed9e446f7 --- /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/guava/README.md b/guava/README.md index 56e6aff50c..60754dbe57 100644 --- a/guava/README.md +++ b/guava/README.md @@ -17,3 +17,4 @@ - [Using Guava CountingOutputStream](http://www.baeldung.com/guava-counting-outputstream) - [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers) - [Quick Guide to the Guava RateLimiter](http://www.baeldung.com/guava-rate-limiter) +- [Hamcrest File Matchers](https://www.baeldung.com/hamcrest-file-matchers) diff --git a/guava/src/test/java/org/baeldung/hamcrest/README.md b/guava/src/test/java/org/baeldung/hamcrest/README.md index 456108d78a..7266ecda3a 100644 --- a/guava/src/test/java/org/baeldung/hamcrest/README.md +++ b/guava/src/test/java/org/baeldung/hamcrest/README.md @@ -1,3 +1,2 @@ ### Relevant Articles: - [Testing with Hamcrest](http://www.baeldung.com/java-junit-hamcrest-guide) -- [Hamcrest File Matchers](http://www.baeldung.com/hamcrest-file-matchers) diff --git a/guest/junit5-example/pom.xml b/guest/junit5-example/pom.xml index 7c0cc3e776..c6370941d1 100644 --- a/guest/junit5-example/pom.xml +++ b/guest/junit5-example/pom.xml @@ -60,7 +60,6 @@ 5.0.0-M4 4.12.0-M4 - 1.4.195 2.8.2 1.0.0-M4 diff --git a/guest/log4j2-example/pom.xml b/guest/log4j2-example/pom.xml index ab55e0b60e..31a32a4562 100644 --- a/guest/log4j2-example/pom.xml +++ b/guest/log4j2-example/pom.xml @@ -41,7 +41,6 @@ - 2.8.8.1 2.8.2 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/tomcat-app/pom.xml b/guest/tomcat-app/pom.xml index 9ce77c758a..ab18023f70 100644 --- a/guest/tomcat-app/pom.xml +++ b/guest/tomcat-app/pom.xml @@ -31,9 +31,9 @@ ${rest-assured.version}
- com.h2database + com.h2 h2 - ${h2database.version} + ${h2.version} runtime @@ -62,7 +62,6 @@ 2.25.1 - 1.4.195 3.0.3 2.8.2 1.69.0 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) diff --git a/guice/pom.xml b/guice/pom.xml index f3e7873245..8ed2b557dc 100644 --- a/guice/pom.xml +++ b/guice/pom.xml @@ -5,8 +5,8 @@ com.baeldung.examples.guice guice 1.0-SNAPSHOT - jar guice + jar com.baeldung @@ -26,4 +26,4 @@ 4.1.0 - + \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/common/Account.java b/guice/src/main/java/com/baeldung/examples/common/Account.java new file mode 100644 index 0000000000..fd2df005ac --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/Account.java @@ -0,0 +1,24 @@ +package com.baeldung.examples.common; + +public class Account { + + private String accountNumber; + private String type; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountService.java b/guice/src/main/java/com/baeldung/examples/common/AccountService.java new file mode 100644 index 0000000000..97a64e3c6e --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AccountService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java new file mode 100644 index 0000000000..18d6777c4a --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AccountServiceImpl implements AccountService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java b/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java new file mode 100644 index 0000000000..5d501f2051 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AudioBookService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AudioBookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java new file mode 100644 index 0000000000..c64e953a58 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AudioBookServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AudioBookServiceImpl implements AudioBookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AuthorService.java b/guice/src/main/java/com/baeldung/examples/common/AuthorService.java new file mode 100644 index 0000000000..9be148b8c3 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AuthorService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface AuthorService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java new file mode 100644 index 0000000000..bac532e469 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AuthorServiceImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class AuthorServiceImpl implements AuthorService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookService.java b/guice/src/main/java/com/baeldung/examples/common/BookService.java new file mode 100644 index 0000000000..56339c1398 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookService.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface BookService { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java new file mode 100644 index 0000000000..aee0d22e51 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java @@ -0,0 +1,7 @@ +package com.baeldung.examples.common; + +public class BookServiceImpl implements BookService { + + private AuthorService authorService; + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDao.java b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java new file mode 100644 index 0000000000..980fee0252 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface PersonDao { + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java new file mode 100644 index 0000000000..ecbf198cc0 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public class PersonDaoImpl implements PersonDao { + +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/Foo.java b/guice/src/main/java/com/baeldung/examples/guice/Foo.java new file mode 100644 index 0000000000..fca32b165b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Foo.java @@ -0,0 +1,4 @@ +package com.baeldung.examples.guice; + +public class Foo { +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java b/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java new file mode 100644 index 0000000000..929013cd2b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/FooProcessor.java @@ -0,0 +1,9 @@ +package com.baeldung.examples.guice; + +import com.google.inject.Inject; + +public class FooProcessor { + + @Inject + private Foo foo; +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java new file mode 100644 index 0000000000..ce12e3e528 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.PersonDao; +import com.google.inject.Inject; + +public class GuicePersonService { + + @Inject + private PersonDao personDao; + + public PersonDao getPersonDao() { + return personDao; + } + + public void setPersonDao(PersonDao personDao) { + this.personDao = personDao; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java new file mode 100644 index 0000000000..0e58d0bacf --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.AccountService; +import com.google.inject.Inject; + +public class GuiceUserService { + + @Inject + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/Person.java b/guice/src/main/java/com/baeldung/examples/guice/Person.java new file mode 100644 index 0000000000..d54b5110eb --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Person.java @@ -0,0 +1,24 @@ +package com.baeldung.examples.guice; + +public class Person { + private String firstName; + + private String 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; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java new file mode 100644 index 0000000000..fbcd36b56a --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java @@ -0,0 +1,50 @@ +package com.baeldung.examples.guice.modules; + +import com.baeldung.examples.common.AccountService; +import com.baeldung.examples.common.AccountServiceImpl; +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.common.BookServiceImpl; +import com.baeldung.examples.common.PersonDao; +import com.baeldung.examples.common.PersonDaoImpl; +import com.baeldung.examples.guice.Foo; +import com.baeldung.examples.guice.Person; +import com.google.inject.AbstractModule; +import com.google.inject.Provider; +import com.google.inject.Provides; + +public class GuiceModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(AccountService.class).to(AccountServiceImpl.class); + bind(Person.class).toConstructor(Person.class.getConstructor()); + // bind(Person.class).toProvider(new Provider() { + // public Person get() { + // Person p = new Person(); + // return p; + // } + // }); + bind(Foo.class).toProvider(new Provider() { + public Foo get() { + return new Foo(); + } + }); + bind(PersonDao.class).to(PersonDaoImpl.class); + + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Provides + public BookService bookServiceGenerator() { + return new BookServiceImpl(); + } + +} diff --git a/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java new file mode 100644 index 0000000000..dd2a89e101 --- /dev/null +++ b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.examples; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.guice.FooProcessor; +import com.baeldung.examples.guice.GuicePersonService; +import com.baeldung.examples.guice.GuiceUserService; +import com.baeldung.examples.guice.Person; +import com.baeldung.examples.guice.modules.GuiceModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class GuiceUnitTest { + + @Test + public void givenAccountServiceInjectedInGuiceUserService_WhenGetAccountServiceInvoked_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuiceUserService guiceUserService = injector.getInstance(GuiceUserService.class); + assertNotNull(guiceUserService.getAccountService()); + } + + @Test + public void givenBookServiceIsRegisteredInModule_WhenBookServiceIsInjected_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + BookService bookService = injector.getInstance(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenMultipleBindingsForPerson_WhenPersonIsInjected_ThenTestFailsByProvisionException() { + Injector injector = Guice.createInjector(new GuiceModule()); + Person person = injector.getInstance(Person.class); + assertNotNull(person); + } + + @Test + public void givenFooInjectedToFooProcessorAsOptionalDependency_WhenFooProcessorIsRetrievedFromContext_ThenCreationExceptionIsNotThrown() { + Injector injector = Guice.createInjector(new GuiceModule()); + FooProcessor fooProcessor = injector.getInstance(FooProcessor.class); + assertNotNull(fooProcessor); + } + + @Test + public void givenGuicePersonServiceConstructorAnnotatedByInject_WhenGuicePersonServiceIsInjected_ThenInstanceWillBeCreatedFromTheConstructor() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuicePersonService personService = injector.getInstance(GuicePersonService.class); + assertNotNull(personService); + } + + @Test + public void givenPersonDaoInjectedToGuicePersonServiceBySetterInjection_WhenGuicePersonServiceIsInjected_ThenPersonDaoInitializedByTheSetter() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuicePersonService personService = injector.getInstance(GuicePersonService.class); + assertNotNull(personService); + assertNotNull(personService.getPersonDao()); + } + +} diff --git a/helidon/helidon-mp/pom.xml b/helidon/helidon-mp/pom.xml index 1f39431886..82d52ca2ef 100644 --- a/helidon/helidon-mp/pom.xml +++ b/helidon/helidon-mp/pom.xml @@ -15,13 +15,18 @@ io.helidon.microprofile.bundles helidon-microprofile-1.2 - 0.10.4 + ${helidon-microprofile.version} org.glassfish.jersey.media jersey-media-json-binding - 2.26 + ${jersey-media-json-binding.version} + + 0.10.4 + 2.26 + + diff --git a/helidon/helidon-se/pom.xml b/helidon/helidon-se/pom.xml index 8982bf048e..ae16fa16e4 100644 --- a/helidon/helidon-se/pom.xml +++ b/helidon/helidon-se/pom.xml @@ -12,10 +12,6 @@ 1.0.0-SNAPSHOT
- - 0.10.4 - - @@ -61,4 +57,8 @@ + + 0.10.4 + + \ No newline at end of file diff --git a/httpclient-simple/.gitignore b/httpclient-simple/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/httpclient-simple/.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/httpclient-simple/README.md b/httpclient-simple/README.md new file mode 100644 index 0000000000..e3535a133e --- /dev/null +++ b/httpclient-simple/README.md @@ -0,0 +1,16 @@ +========= +## This module contains articles that are part of the HTTPClient Ebook + +- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) +- [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) +- [HttpClient Timeout](http://www.baeldung.com/httpclient-timeout) +- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) +- [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) +- [Posting with HttpClient](https://www.baeldung.com/httpclient-post-http-request) + + +### Running the Tests +To run the live tests, use the command: mvn clean install -Plive +This will start an embedded Jetty server on port 8082 using the Cargo plugin configured in the pom.xml file, +for the live Maven profile diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml new file mode 100644 index 0000000000..efcf0452e2 --- /dev/null +++ b/httpclient-simple/pom.xml @@ -0,0 +1,312 @@ + + 4.0.0 + com.baeldung + httpclient-simple + 0.1-SNAPSHOT + httpclient-simple + war + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + + + + org.springframework.security + spring-security-web + ${spring.version} + + + org.springframework.security + spring-security-config + ${spring.version} + + + + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework + spring-expression + ${spring.version} + + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + + org.springframework + spring-oxm + ${spring.version} + + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + + + commons-logging + commons-logging + + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-logging + commons-logging + + + + + org.apache.httpcomponents + fluent-hc + ${httpclient.version} + + + commons-logging + commons-logging + + + + + org.apache.httpcomponents + httpmime + ${httpclient.version} + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.apache.httpcomponents + httpasyncclient + ${httpasyncclient.version} + + + commons-logging + commons-logging + + + + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + + + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + + javax.servlet + jstl + ${jstl.version} + runtime + + + + + + com.google.guava + guava + ${guava.version} + + + + + + org.springframework + spring-test + ${spring.version} + test + + + + + httpclient-simple + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty8x + embedded + + + + + + + 8082 + + + + + + + + + + live + + + + org.codehaus.cargo + cargo-maven2-plugin + + + start-server + pre-integration-test + + start + + + + stop-server + post-integration-test + + stop + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + none + + + **/*LiveTest.java + + + cargo + + + + + + + + + + + + + + 19.0 + 3.5 + 1.10 + 4.1.4 + + 2.5.1 + 4.4.11 + 4.5.8 + + 2.6 + 1.6.1 + + + \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java b/httpclient-simple/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java new file mode 100644 index 0000000000..380ff9df6b --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/basic/MyBasicAuthenticationEntryPoint.java @@ -0,0 +1,30 @@ +package com.baeldung.basic; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +@Component +public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint { + + @Override + public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException { + response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\""); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + final PrintWriter writer = response.getWriter(); + writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage()); + } + + @Override + public void afterPropertiesSet() throws Exception { + setRealmName("Baeldung"); + super.afterPropertiesSet(); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java b/httpclient-simple/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java new file mode 100644 index 0000000000..81f82a2c1c --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java @@ -0,0 +1,39 @@ +package com.baeldung.client; + +import java.net.URI; + +import org.apache.http.HttpHost; +import org.apache.http.client.AuthCache; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory { + + HttpHost host; + + public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) { + super(); + this.host = host; + } + + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + return createHttpContext(); + } + + private HttpContext createHttpContext() { + + AuthCache authCache = new BasicAuthCache(); + + BasicScheme basicAuth = new BasicScheme(); + authCache.put(host, basicAuth); + + BasicHttpContext localcontext = new BasicHttpContext(); + localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache); + return localcontext; + } +} \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/client/RestTemplateFactory.java b/httpclient-simple/src/main/java/com/baeldung/client/RestTemplateFactory.java new file mode 100644 index 0000000000..aac4f8cebd --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/client/RestTemplateFactory.java @@ -0,0 +1,44 @@ +package com.baeldung.client; + +import org.apache.http.HttpHost; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +public class RestTemplateFactory implements FactoryBean, InitializingBean { + private RestTemplate restTemplate; + + public RestTemplateFactory() { + super(); + } + + // API + + @Override + public RestTemplate getObject() { + return restTemplate; + } + + @Override + public Class getObjectType() { + return RestTemplate.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public void afterPropertiesSet() { + HttpHost host = new HttpHost("localhost", 8082, "http"); + final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host); + restTemplate = new RestTemplate(requestFactory); + restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass")); + } + +} \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/client/spring/ClientConfig.java b/httpclient-simple/src/main/java/com/baeldung/client/spring/ClientConfig.java new file mode 100644 index 0000000000..03994b55a5 --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/client/spring/ClientConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.client.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.baeldung.client") +public class ClientConfig { + + public ClientConfig() { + super(); + } + + // beans + +} \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/filter/CustomFilter.java b/httpclient-simple/src/main/java/com/baeldung/filter/CustomFilter.java new file mode 100644 index 0000000000..6bb12610fa --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/filter/CustomFilter.java @@ -0,0 +1,18 @@ +package com.baeldung.filter; + +import org.springframework.web.filter.GenericFilterBean; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; + +public class CustomFilter extends GenericFilterBean { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + chain.doFilter(request, response); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java b/httpclient-simple/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java new file mode 100644 index 0000000000..fb597e46c8 --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/filter/CustomWebSecurityConfigurerAdapter.java @@ -0,0 +1,49 @@ +package com.baeldung.filter; + +import com.baeldung.security.RestAuthenticationEntryPoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +@Configuration +@EnableWebSecurity +public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { + + @Autowired private RestAuthenticationEntryPoint authenticationEntryPoint; + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user1") + .password(passwordEncoder().encode("user1Pass")) + .authorities("ROLE_USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/securityNone") + .permitAll() + .anyRequest() + .authenticated() + .and() + .httpBasic() + .authenticationEntryPoint(authenticationEntryPoint); + + http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/httpclient-simple/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java b/httpclient-simple/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java new file mode 100644 index 0000000000..7dc53e3e1e --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java @@ -0,0 +1,48 @@ +package com.baeldung.security; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.util.StringUtils; + +public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { + + private RequestCache requestCache = new HttpSessionRequestCache(); + + @Override + public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws ServletException, IOException { + final SavedRequest savedRequest = requestCache.getRequest(request, response); + + if (savedRequest == null) { + super.onAuthenticationSuccess(request, response, authentication); + + return; + } + final String targetUrlParameter = getTargetUrlParameter(); + if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { + requestCache.removeRequest(request, response); + super.onAuthenticationSuccess(request, response, authentication); + + return; + } + + clearAuthenticationAttributes(request); + + // Use the DefaultSavedRequest URL + // final String targetUrl = savedRequest.getRedirectUrl(); + // logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl); + // getRedirectStrategy().sendRedirect(request, response, targetUrl); + } + + public void setRequestCache(final RequestCache requestCache) { + this.requestCache = requestCache; + } +} diff --git a/httpclient-simple/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java b/httpclient-simple/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java new file mode 100644 index 0000000000..1ae89adb89 --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/security/RestAuthenticationEntryPoint.java @@ -0,0 +1,23 @@ +package com.baeldung.security; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +/** + * The Entry Point will not redirect to any sort of Login - it will return the 401 + */ +@Component +public final class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + } + +} \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/spring/SecSecurityConfig.java b/httpclient-simple/src/main/java/com/baeldung/spring/SecSecurityConfig.java new file mode 100644 index 0000000000..4ba9d47f8d --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/spring/SecSecurityConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; + +@Configuration +@ImportResource({ "classpath:webSecurityConfig.xml" }) +@ComponentScan("com.baeldung.security") +public class SecSecurityConfig { + + public SecSecurityConfig() { + super(); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/spring/WebConfig.java b/httpclient-simple/src/main/java/com/baeldung/spring/WebConfig.java new file mode 100644 index 0000000000..8d5c1dc7f1 --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/spring/WebConfig.java @@ -0,0 +1,30 @@ +package com.baeldung.spring; + +import java.util.List; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@EnableWebMvc +@ComponentScan("com.baeldung.web") +public class WebConfig implements WebMvcConfigurer { + + public WebConfig() { + super(); + } + + // beans + + @Override + public void configureMessageConverters(final List> converters) { + converters.add(new MappingJackson2HttpMessageConverter()); + } + + // + +} \ No newline at end of file diff --git a/httpclient-simple/src/main/java/com/baeldung/web/controller/BarController.java b/httpclient-simple/src/main/java/com/baeldung/web/controller/BarController.java new file mode 100644 index 0000000000..02e6af03af --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/web/controller/BarController.java @@ -0,0 +1,31 @@ +package com.baeldung.web.controller; + +import com.baeldung.web.dto.Bar; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value = "/bars") +public class BarController { + + @Autowired + private ApplicationEventPublisher eventPublisher; + + public BarController() { + super(); + } + + // API + + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @ResponseBody + public Bar findOne(@PathVariable("id") final Long id) { + return new Bar(); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/web/controller/FooController.java b/httpclient-simple/src/main/java/com/baeldung/web/controller/FooController.java new file mode 100644 index 0000000000..461a5e351a --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/web/controller/FooController.java @@ -0,0 +1,33 @@ +package com.baeldung.web.controller; + +import com.baeldung.web.dto.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value = "/foos") +public class FooController { + + @Autowired + private ApplicationEventPublisher eventPublisher; + + public FooController() { + super(); + } + + // API + + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @ResponseBody + @PreAuthorize("hasRole('ROLE_USER')") + public Foo findOne(@PathVariable("id") final Long id) { + return new Foo(); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/web/dto/Bar.java b/httpclient-simple/src/main/java/com/baeldung/web/dto/Bar.java new file mode 100644 index 0000000000..eb139b0ec1 --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/web/dto/Bar.java @@ -0,0 +1,14 @@ +package com.baeldung.web.dto; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Bar implements Serializable { + + public Bar() { + super(); + } + +} diff --git a/httpclient-simple/src/main/java/com/baeldung/web/dto/Foo.java b/httpclient-simple/src/main/java/com/baeldung/web/dto/Foo.java new file mode 100644 index 0000000000..23cfab132d --- /dev/null +++ b/httpclient-simple/src/main/java/com/baeldung/web/dto/Foo.java @@ -0,0 +1,14 @@ +package com.baeldung.web.dto; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Foo implements Serializable { + + public Foo() { + super(); + } + +} diff --git a/httpclient-simple/src/main/resources/logback.xml b/httpclient-simple/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/httpclient-simple/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/httpclient-simple/src/main/resources/webSecurityConfig.xml b/httpclient-simple/src/main/resources/webSecurityConfig.xml new file mode 100644 index 0000000000..2ff9a1de15 --- /dev/null +++ b/httpclient-simple/src/main/resources/webSecurityConfig.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml b/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml new file mode 100644 index 0000000000..1dbff70b83 --- /dev/null +++ b/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/httpclient-simple/src/main/webapp/WEB-INF/web.xml b/httpclient-simple/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4b2dd54266 --- /dev/null +++ b/httpclient-simple/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,43 @@ + + + + Spring Security Custom Application + + + + contextClass + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + contextConfigLocation + com.baeldung.spring + + + + org.springframework.web.context.ContextLoaderListener + + + + + api + org.springframework.web.servlet.DispatcherServlet + 1 + + + api + /api/* + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + springSecurityFilterChain + /* + + + \ No newline at end of file diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/client/ClientLiveTest.java similarity index 82% rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/client/ClientLiveTest.java index 2a668f827a..78e9813f06 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/client/ClientLiveTest.java @@ -1,11 +1,11 @@ -package org.baeldung.client; +package com.baeldung.client; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import org.baeldung.client.spring.ClientConfig; -import org.baeldung.web.dto.Foo; +import com.baeldung.client.spring.ClientConfig; +import com.baeldung.web.dto.Foo; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -33,13 +33,13 @@ public class ClientLiveTest { @Test public final void whenSecuredRestApiIsConsumed_then200OK() { - final ResponseEntity responseEntity = secureRestTemplate.exchange("http://localhost:8082/spring-security-rest-basic-auth/api/foos/1", HttpMethod.GET, null, Foo.class); + final ResponseEntity responseEntity = secureRestTemplate.exchange("http://localhost:8082/httpclient-simple/api/foos/1", HttpMethod.GET, null, Foo.class); assertThat(responseEntity.getStatusCode().value(), is(200)); } @Test(expected = ResourceAccessException.class) public final void whenHttpsUrlIsConsumed_thenException() { - final String urlOverHttps = "https://localhost:8443/spring-security-rest-basic-auth/api/bars/1"; + final String urlOverHttps = "https://localhost:8443/httpclient-simple/api/bars/1"; final ResponseEntity response = new RestTemplate().exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200)); } diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java b/httpclient-simple/src/test/java/com/baeldung/client/RestClientLiveManualTest.java similarity index 60% rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java rename to httpclient-simple/src/test/java/com/baeldung/client/RestClientLiveManualTest.java index 104129b663..a485641b34 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/client/RestClientLiveManualTest.java @@ -1,4 +1,4 @@ -package org.baeldung.client; +package com.baeldung.client; import static org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; import static org.hamcrest.Matchers.equalTo; @@ -8,19 +8,24 @@ import java.io.IOException; import java.security.GeneralSecurityException; import java.security.cert.X509Certificate; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLContext; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.ssl.SSLContexts; import org.junit.Ignore; import org.junit.Test; import org.springframework.http.HttpMethod; @@ -34,29 +39,48 @@ import org.springframework.web.client.RestTemplate; * */ public class RestClientLiveManualTest { - final String urlOverHttps = "http://localhost:8082/spring-security-rest-basic-auth/api/bars/1"; + final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1"; // tests // old httpClient will throw UnsupportedOperationException @Ignore @Test - public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException() throws GeneralSecurityException { + public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk_1() throws GeneralSecurityException { final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); final CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient(); - final TrustStrategy acceptingTrustStrategy = new TrustStrategy() { - @Override - public final boolean isTrusted(final X509Certificate[] certificate, final String authType) { - return true; - } - }; + final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; + final SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, ALLOW_ALL_HOSTNAME_VERIFIER); httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 8443, sf)); final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class); assertThat(response.getStatusCode().value(), equalTo(200)); } + + // new httpClient : 4.4 and above + @Test + public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenOk_2() throws GeneralSecurityException { + + final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true; + final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); + final Registry socketFactoryRegistry = RegistryBuilder. create() + .register("https", sslsf) + .register("http", new PlainConnectionSocketFactory()) + .build(); + + final BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry); + final CloseableHttpClient httpClient = HttpClients.custom() + .setSSLSocketFactory(sslsf) + .setConnectionManager(connectionManager) + .build(); + + final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class); + assertThat(response.getStatusCode().value(), equalTo(200)); + } @Test public final void givenAcceptingAllCertificatesUsing4_4_whenHttpsUrlIsConsumed_thenCorrect() throws ClientProtocolException, IOException { diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientHeadersLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientHeadersLiveTest.java similarity index 99% rename from httpclient/src/test/java/org/baeldung/httpclient/HttpClientHeadersLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientHeadersLiveTest.java index 51c3817da5..44262851fd 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientHeadersLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientHeadersLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient; +package com.baeldung.httpclient; import com.google.common.collect.Lists; import org.apache.http.Header; diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientPostingLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientPostingLiveTest.java similarity index 93% rename from httpclient/src/test/java/org/baeldung/httpclient/HttpClientPostingLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientPostingLiveTest.java index 39ed8f09ef..f5dff8d757 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientPostingLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientPostingLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient; +package com.baeldung.httpclient; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -32,7 +32,7 @@ import static org.junit.Assert.assertThat; * NOTE : Need module spring-rest to be running */ public class HttpClientPostingLiveTest { - private static final String SAMPLE_URL = "http://localhost:8082/spring-rest/users"; + private static final String SAMPLE_URL = "http://www.example.com"; private static final String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://browserspy.dk/password-ok.php"; private static final String DEFAULT_USER = "test"; private static final String DEFAULT_PASS = "test"; @@ -69,7 +69,7 @@ public class HttpClientPostingLiveTest { @Test public void whenPostJsonUsingHttpClient_thenCorrect() throws IOException { final CloseableHttpClient client = HttpClients.createDefault(); - final HttpPost httpPost = new HttpPost(SAMPLE_URL + "/detail"); + final HttpPost httpPost = new HttpPost(SAMPLE_URL); final String json = "{\"id\":1,\"name\":\"John\"}"; final StringEntity entity = new StringEntity(json); @@ -92,7 +92,7 @@ public class HttpClientPostingLiveTest { @Test public void whenSendMultipartRequestUsingHttpClient_thenCorrect() throws IOException { final CloseableHttpClient client = HttpClients.createDefault(); - final HttpPost httpPost = new HttpPost(SAMPLE_URL + "/multipart"); + final HttpPost httpPost = new HttpPost(SAMPLE_URL); final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody("username", DEFAULT_USER); @@ -110,7 +110,7 @@ public class HttpClientPostingLiveTest { @Test public void whenUploadFileUsingHttpClient_thenCorrect() throws IOException { final CloseableHttpClient client = HttpClients.createDefault(); - final HttpPost httpPost = new HttpPost(SAMPLE_URL + "/upload"); + final HttpPost httpPost = new HttpPost(SAMPLE_URL); final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("file", new File("src/test/resources/test.in"), ContentType.APPLICATION_OCTET_STREAM, "file.ext"); @@ -126,7 +126,7 @@ public class HttpClientPostingLiveTest { @Test public void whenGetUploadFileProgressUsingHttpClient_thenCorrect() throws IOException { final CloseableHttpClient client = HttpClients.createDefault(); - final HttpPost httpPost = new HttpPost(SAMPLE_URL + "/upload"); + final HttpPost httpPost = new HttpPost(SAMPLE_URL); final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("file", new File("src/test/resources/test.in"), ContentType.APPLICATION_OCTET_STREAM, "file.ext"); diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientTimeoutLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientTimeoutLiveTest.java similarity index 59% rename from httpclient/src/test/java/org/baeldung/httpclient/HttpClientTimeoutLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientTimeoutLiveTest.java index 74255e416c..8bd7042dc6 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientTimeoutLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientTimeoutLiveTest.java @@ -1,20 +1,28 @@ -package org.baeldung.httpclient; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.config.SocketConfig; -import org.apache.http.conn.HttpHostConnectException; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.junit.After; -import org.junit.Test; - -import java.io.IOException; +package com.baeldung.httpclient; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.HttpParams; +import org.junit.After; +import org.junit.Ignore; +import org.junit.Test; + public class HttpClientTimeoutLiveTest { private CloseableHttpResponse response; @@ -25,6 +33,20 @@ public class HttpClientTimeoutLiveTest { } // tests + @Test + public final void givenUsingOldApi_whenSettingTimeoutViaParameter_thenCorrect() throws IOException { + + DefaultHttpClient httpClient = new DefaultHttpClient(); + int timeout = 5; // seconds + HttpParams httpParams = httpClient.getParams(); + httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000); + httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000); + httpParams.setParameter(ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000)); + + final HttpGet request = new HttpGet("http://www.github.com"); + HttpResponse execute = httpClient.execute(request); + assertThat(execute.getStatusLine().getStatusCode(), equalTo(200)); + } @Test public final void givenUsingNewApi_whenSettingTimeoutViaRequestConfig_thenCorrect() throws IOException { @@ -33,8 +55,6 @@ public class HttpClientTimeoutLiveTest { final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); final HttpGet request = new HttpGet("http://www.github.com"); - // httpParams.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000)); // https://issues.apache.org/jira/browse/HTTPCLIENT-1418 - response = client.execute(request); assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); @@ -71,7 +91,8 @@ public class HttpClientTimeoutLiveTest { /** * This simulates a timeout against a domain with multiple routes/IPs to it (not a single raw IP) */ - @Test(expected = HttpHostConnectException.class) + @Test(expected = ConnectTimeoutException.class) + @Ignore public final void givenTimeoutIsConfigured_whenTimingOut_thenTimeoutException() throws IOException { final int timeout = 3; @@ -81,5 +102,28 @@ public class HttpClientTimeoutLiveTest { final HttpGet request = new HttpGet("http://www.google.com:81"); client.execute(request); } + + @Test + public void whenSecuredRestApiIsConsumed_then200OK() throws IOException { + CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + int timeout = 20; // seconds + RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout * 1000) + .setConnectTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build(); + HttpGet getMethod = new HttpGet("http://localhost:8082/httpclient-simple/api/bars/1"); + getMethod.setConfig(requestConfig); + + int hardTimeout = 5; // seconds + TimerTask task = new TimerTask() { + @Override + public void run() { + getMethod.abort(); + } + }; + new Timer(true).schedule(task, hardTimeout * 1000); + + HttpResponse response = httpClient.execute(getMethod); + System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode()); + } + } diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpsClientSslLiveTest.java similarity index 81% rename from httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/HttpsClientSslLiveTest.java index 4eadfe24d5..24ceab0069 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpsClientSslLiveTest.java @@ -1,32 +1,31 @@ -package org.baeldung.httpclient; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.scheme.SchemeRegistry; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; -import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingClientConnectionManager; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.SSLContexts; -import org.junit.Test; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import java.io.IOException; -import java.security.GeneralSecurityException; +package com.baeldung.httpclient; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; +import java.io.IOException; +import java.security.GeneralSecurityException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.SSLContexts; +import org.junit.Test; + /** * This test requires a localhost server over HTTPS
* It should only be manually run, not part of the automated build @@ -50,16 +49,22 @@ public class HttpsClientSslLiveTest { .getStatusCode(), equalTo(200)); } - @SuppressWarnings("deprecation") @Test public final void givenHttpClientPre4_3_whenAcceptingAllCertificates_thenCanConsumeHttpsUriWithSelfSignedCertificate() throws IOException, GeneralSecurityException { final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true; - final SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - final SchemeRegistry registry = new SchemeRegistry(); - registry.register(new Scheme("https", 443, sf)); - final ClientConnectionManager ccm = new PoolingClientConnectionManager(registry); + + final SSLContext sslContext = SSLContexts.custom() + .loadTrustMaterial(null, acceptingTrustStrategy) + .build(); - final CloseableHttpClient httpClient = new DefaultHttpClient(ccm); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); + Registry socketFactoryRegistry = RegistryBuilder. create().register("https", sslsf).build(); + PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + + final CloseableHttpClient httpClient = HttpClients.custom() + .setSSLSocketFactory(sslsf) + .setConnectionManager(clientConnectionManager) + .build(); final HttpGet getMethod = new HttpGet(HOST_WITH_SSL); final HttpResponse response = httpClient.execute(getMethod); @@ -76,10 +81,9 @@ public class HttpsClientSslLiveTest { .loadTrustMaterial(null, acceptingTrustStrategy) .build(); - final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); final CloseableHttpClient httpClient = HttpClients.custom() - .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) .setSSLSocketFactory(sslsf) .build(); diff --git a/httpclient/src/test/java/org/baeldung/httpclient/ProgressEntityWrapper.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/ProgressEntityWrapper.java similarity index 98% rename from httpclient/src/test/java/org/baeldung/httpclient/ProgressEntityWrapper.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/ProgressEntityWrapper.java index cd00d8711a..c7adf51b3e 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/ProgressEntityWrapper.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/ProgressEntityWrapper.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient; +package com.baeldung.httpclient; import java.io.FilterOutputStream; import java.io.IOException; diff --git a/httpclient-simple/src/test/java/com/baeldung/httpclient/ResponseUtil.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/ResponseUtil.java new file mode 100644 index 0000000000..e9ea08a723 --- /dev/null +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/ResponseUtil.java @@ -0,0 +1,26 @@ +package com.baeldung.httpclient; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; + +import java.io.IOException; + +public final class ResponseUtil { + private ResponseUtil() { + } + + public static void closeResponse(CloseableHttpResponse response) throws IOException { + if (response == null) { + return; + } + + try { + final HttpEntity entity = response.getEntity(); + if (entity != null) { + entity.getContent().close(); + } + } finally { + response.close(); + } + } +} diff --git a/httpclient/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/base/HttpClientBasicLiveTest.java similarity index 96% rename from httpclient/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/base/HttpClientBasicLiveTest.java index fee9dc4343..d1b093394e 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/base/HttpClientBasicLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient.base; +package com.baeldung.httpclient.base; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; @@ -8,7 +8,7 @@ import org.apache.http.entity.ContentType; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; -import org.baeldung.httpclient.ResponseUtil; +import com.baeldung.httpclient.ResponseUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientAuthLiveTest.java similarity index 95% rename from httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientAuthLiveTest.java index c9956e5852..0f7018a9ac 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientAuthLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient.sec; +package com.baeldung.httpclient.sec; import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpHeaders; @@ -17,25 +17,24 @@ import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.protocol.HttpContext; -import org.baeldung.httpclient.ResponseUtil; +import com.baeldung.httpclient.ResponseUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; /* - * NOTE : Need module spring-security-rest-basic-auth to be running + * NOTE : Need module httpclient-simple to be running */ public class HttpClientAuthLiveTest { - private static final String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://localhost:8081/spring-security-rest-basic-auth/api/foos/1"; + private static final String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://localhost:8082/httpclient-simple/api/foos/1"; private static final String DEFAULT_USER = "user1"; private static final String DEFAULT_PASS = "user1Pass"; @@ -111,7 +110,7 @@ public class HttpClientAuthLiveTest { } private HttpContext context() { - final HttpHost targetHost = new HttpHost("localhost", 8080, "http"); + final HttpHost targetHost = new HttpHost("localhost", 8082, "http"); final CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS)); diff --git a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientCookieLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java similarity index 97% rename from httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientCookieLiveTest.java rename to httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java index ba27aca08d..287b6e996c 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientCookieLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.httpclient.sec; +package com.baeldung.httpclient.sec; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.CloseableHttpResponse; @@ -10,7 +10,7 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; -import org.baeldung.httpclient.ResponseUtil; +import com.baeldung.httpclient.ResponseUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java b/httpclient-simple/src/test/java/com/baeldung/test/LiveTestSuite.java similarity index 64% rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java rename to httpclient-simple/src/test/java/com/baeldung/test/LiveTestSuite.java index 8c9b48d056..c864349e02 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java +++ b/httpclient-simple/src/test/java/com/baeldung/test/LiveTestSuite.java @@ -1,7 +1,7 @@ -package org.baeldung.test; +package com.baeldung.test; -import org.baeldung.client.ClientLiveTest; -import org.baeldung.client.RestClientLiveManualTest; +import com.baeldung.client.ClientLiveTest; +import com.baeldung.client.RestClientLiveManualTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; diff --git a/httpclient-simple/src/test/resources/.gitignore b/httpclient-simple/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/httpclient-simple/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/httpclient-simple/src/test/resources/test.in b/httpclient-simple/src/test/resources/test.in new file mode 100644 index 0000000000..95d09f2b10 --- /dev/null +++ b/httpclient-simple/src/test/resources/test.in @@ -0,0 +1 @@ +hello world \ No newline at end of file diff --git a/httpclient/README.md b/httpclient/README.md index 93e0f3c9e1..a5fc29b089 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -7,18 +7,13 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) -- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) -- [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) +- [HttpClient 4 – Cancel 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) -- [HttpClient – Set Custom Header](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) - [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) diff --git a/httpclient/pom.xml b/httpclient/pom.xml index c9f9808ede..def3a05816 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -122,11 +122,10 @@ 19.0 3.5 1.10 - 4.1.2 + 4.1.4 2.5.1 - 4.4.5 - 4.5.3 + 4.5.8 1.6.1 diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java index d39697c0a9..47a587885e 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java +++ b/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java @@ -4,7 +4,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import java.io.IOException; -import java.security.cert.X509Certificate; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -18,8 +17,7 @@ import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.BasicCredentialsProvider; @@ -31,6 +29,7 @@ import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor; import org.apache.http.nio.reactor.ConnectingIOReactor; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; +import org.apache.http.ssl.SSLContexts; import org.junit.Test; public class HttpAsyncClientLiveTest { @@ -104,7 +103,7 @@ public class HttpAsyncClientLiveTest { final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true; final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); - final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setSSLHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER).setSSLContext(sslContext).build(); + final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(sslContext).build(); client.start(); final HttpGet request = new HttpGet(HOST_WITH_SSL); diff --git a/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java index 0f8ebefe6c..cf945098db 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java +++ b/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java @@ -327,7 +327,8 @@ public class HttpClientConnectionManagementLiveTest { // 8.1 public final void whenHttpClientChecksStaleConns_thenNoExceptions() { poolingConnManager = new PoolingHttpClientConnectionManager(); - client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build()).setConnectionManager(poolingConnManager).build(); + poolingConnManager.setValidateAfterInactivity(1000); + client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().build()).setConnectionManager(poolingConnManager).build(); } @Test diff --git a/hystrix/pom.xml b/hystrix/pom.xml index fb044588de..7bb3e98246 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -64,8 +64,6 @@ 1.5.8 0.20.7 - - 1.3 2.6 2.7 diff --git a/jackson-2/.gitignore b/jackson-2/.gitignore new file mode 100644 index 0000000000..4b1cfaf098 --- /dev/null +++ b/jackson-2/.gitignore @@ -0,0 +1,16 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear + +# Files +/src/main/resources/orderOutput.yaml \ No newline at end of file diff --git a/jackson-2/README.md b/jackson-2/README.md new file mode 100644 index 0000000000..d8c233a00e --- /dev/null +++ b/jackson-2/README.md @@ -0,0 +1,12 @@ +========= + +## Jackson Cookbooks and Examples + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) +- [How to Process YAML with Jackson](https://www.baeldung.com/jackson-yaml) +- [Working with Tree Model Nodes in Jackson](https://www.baeldung.com/jackson-json-node-tree-model) +- [Converting JSON to CSV in Java](https://www.baeldung.com/java-converting-json-to-csv) diff --git a/jackson-2/pom.xml b/jackson-2/pom.xml new file mode 100644 index 0000000000..2fff1f8706 --- /dev/null +++ b/jackson-2/pom.xml @@ -0,0 +1,73 @@ + + 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} + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + ${jackson.version} + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + jackson-2 + + + src/main/resources + true + + + + + + + + 3.11.0 + + + diff --git a/jackson-2/src/main/java/com/baeldung/jackson/csv/JsonCsvConverter.java b/jackson-2/src/main/java/com/baeldung/jackson/csv/JsonCsvConverter.java new file mode 100644 index 0000000000..71c6de4d7e --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/csv/JsonCsvConverter.java @@ -0,0 +1,59 @@ +package com.baeldung.jackson.csv; + +import java.io.File; +import java.io.IOException; + +import com.baeldung.jackson.entities.OrderLine; +import com.baeldung.jackson.mixin.OrderLineForCsv; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; +import com.fasterxml.jackson.dataformat.csv.CsvSchema.Builder; + +public class JsonCsvConverter { + + public static void JsonToCsv(File jsonFile, File csvFile) throws IOException { + JsonNode jsonTree = new ObjectMapper().readTree(jsonFile); + + Builder csvSchemaBuilder = CsvSchema.builder(); + JsonNode firstObject = jsonTree.elements().next(); + firstObject.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} ); + CsvSchema csvSchema = csvSchemaBuilder + .build() + .withHeader(); + + CsvMapper csvMapper = new CsvMapper(); + csvMapper.writerFor(JsonNode.class) + .with(csvSchema) + .writeValue(csvFile, jsonTree); + } + + public static void csvToJson(File csvFile, File jsonFile) throws IOException { + CsvSchema orderLineSchema = CsvSchema.emptySchema().withHeader(); + CsvMapper csvMapper = new CsvMapper(); + MappingIterator orderLines = csvMapper.readerFor(OrderLine.class) + .with(orderLineSchema) + .readValues(csvFile); + + new ObjectMapper() + .configure(SerializationFeature.INDENT_OUTPUT, true) + .writeValue(jsonFile, orderLines.readAll()); + } + + public static void JsonToFormattedCsv(File jsonFile, File csvFile) throws IOException { + CsvMapper csvMapper = new CsvMapper(); + CsvSchema csvSchema = csvMapper + .schemaFor(OrderLineForCsv.class) + .withHeader(); + csvMapper.addMixIn(OrderLine.class, OrderLineForCsv.class); + + OrderLine[] orderLines = new ObjectMapper() + .readValue(jsonFile, OrderLine[].class); + csvMapper.writerFor(OrderLine[].class) + .with(csvSchema) + .writeValue(csvFile, orderLines); + } +} diff --git a/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java new file mode 100644 index 0000000000..2075b7879b --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java @@ -0,0 +1,68 @@ +package com.baeldung.jackson.entities; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +public class Order { + private String orderNo; + private LocalDate date; + private String customerName; + private List orderLines; + + public Order() { + + } + + public Order(String orderNo, LocalDate date, String customerName, List orderLines) { + super(); + this.orderNo = orderNo; + this.date = date; + this.customerName = customerName; + this.orderLines = orderLines; + } + + public String getOrderNo() { + return orderNo; + } + + public void setOrderNo(String orderNo) { + this.orderNo = orderNo; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public List getOrderLines() { + if (orderLines == null) { + orderLines = new ArrayList<>(); + } + return orderLines; + } + + public void setOrderLines(List orderLines) { + if (orderLines == null) { + orderLines = new ArrayList<>(); + } + this.orderLines = orderLines; + } + + @Override + public String toString() { + return "Order [orderNo=" + orderNo + ", date=" + date + ", customerName=" + customerName + ", orderLines=" + orderLines + "]"; + } + +} diff --git a/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java new file mode 100644 index 0000000000..858d094dd1 --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java @@ -0,0 +1,49 @@ +package com.baeldung.jackson.entities; + +import java.math.BigDecimal; + +public class OrderLine { + private String item; + private int quantity; + private BigDecimal unitPrice; + + public OrderLine() { + + } + + public OrderLine(String item, int quantity, BigDecimal unitPrice) { + super(); + this.item = item; + this.quantity = quantity; + this.unitPrice = unitPrice; + } + + public String getItem() { + return item; + } + + public void setItem(String item) { + this.item = item; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public BigDecimal getUnitPrice() { + return unitPrice; + } + + public void setUnitPrice(BigDecimal unitPrice) { + this.unitPrice = unitPrice; + } + + @Override + public String toString() { + return "OrderLine [item=" + item + ", quantity=" + quantity + ", unitPrice=" + unitPrice + "]"; + } +} diff --git a/jackson-2/src/main/java/com/baeldung/jackson/entities/Weather.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/Weather.java new file mode 100644 index 0000000000..4a8cea052f --- /dev/null +++ b/jackson-2/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-2/src/main/java/com/baeldung/jackson/mixin/OrderLineForCsv.java b/jackson-2/src/main/java/com/baeldung/jackson/mixin/OrderLineForCsv.java new file mode 100644 index 0000000000..05d70a8053 --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/mixin/OrderLineForCsv.java @@ -0,0 +1,25 @@ +package com.baeldung.jackson.mixin; + +import java.math.BigDecimal; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonPropertyOrder({ + "count", + "name" +}) +public abstract class OrderLineForCsv { + + @JsonProperty("name") + private String item; + + @JsonProperty("count") + private int quantity; + + @JsonIgnore + private BigDecimal unitPrice; + + +} diff --git a/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java b/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java new file mode 100644 index 0000000000..f582772587 --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java @@ -0,0 +1,62 @@ +package com.baeldung.jackson.node; + +import java.util.Iterator; +import java.util.Map.Entry; + +import com.fasterxml.jackson.databind.JsonNode; + +public class JsonNodeIterator { + + private static final String NEW_LINE = "\n"; + private static final String FIELD_DELIMITER = ": "; + private static final String ARRAY_PREFIX = "- "; + private static final String YAML_PREFIX = " "; + + public String toYaml(JsonNode root) { + StringBuilder yaml = new StringBuilder(); + processNode(root, yaml, 0); + return yaml.toString(); + } + + private void processNode(JsonNode jsonNode, StringBuilder yaml, int depth) { + if (jsonNode.isValueNode()) { + yaml.append(jsonNode.asText()); + } + else if (jsonNode.isArray()) { + for (JsonNode arrayItem : jsonNode) { + appendNodeToYaml(arrayItem, yaml, depth, true); + } + } + else if (jsonNode.isObject()) { + appendNodeToYaml(jsonNode, yaml, depth, false); + } + } + + private void appendNodeToYaml(JsonNode node, StringBuilder yaml, int depth, boolean isArrayItem) { + Iterator> fields = node.fields(); + boolean isFirst = true; + while (fields.hasNext()) { + Entry jsonField = fields.next(); + addFieldNameToYaml(yaml, jsonField.getKey(), depth, isArrayItem && isFirst); + processNode(jsonField.getValue(), yaml, depth+1); + isFirst = false; + } + + } + +private void addFieldNameToYaml(StringBuilder yaml, String fieldName, int depth, boolean isFirstInArray) { + if (yaml.length()>0) { + yaml.append(NEW_LINE); + int requiredDepth = (isFirstInArray) ? depth-1 : depth; + for(int i = 0; i < requiredDepth; i++) { + yaml.append(YAML_PREFIX); + } + if (isFirstInArray) { + yaml.append(ARRAY_PREFIX); + } + } + yaml.append(fieldName); + yaml.append(FIELD_DELIMITER); +} + +} 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-2/src/main/resources/orderInput.yaml b/jackson-2/src/main/resources/orderInput.yaml new file mode 100644 index 0000000000..0aaa6186a2 --- /dev/null +++ b/jackson-2/src/main/resources/orderInput.yaml @@ -0,0 +1,11 @@ +orderNo: A001 +date: 2019-04-17 +customerName: Customer, Joe +orderLines: + - item: No. 9 Sprockets + quantity: 12 + unitPrice: 1.23 + - item: Widget (10mm) + quantity: 4 + unitPrice: 3.45 + \ No newline at end of file diff --git a/jackson-2/src/main/resources/orderLines.csv b/jackson-2/src/main/resources/orderLines.csv new file mode 100644 index 0000000000..e15e12f2bf --- /dev/null +++ b/jackson-2/src/main/resources/orderLines.csv @@ -0,0 +1,3 @@ +item,quantity,unitPrice +"No. 9 Sprockets",12,1.23 +"Widget (10mm)",4,3.45 diff --git a/jackson-2/src/main/resources/orderLines.json b/jackson-2/src/main/resources/orderLines.json new file mode 100644 index 0000000000..64f18e1673 --- /dev/null +++ b/jackson-2/src/main/resources/orderLines.json @@ -0,0 +1,9 @@ +[ { + "item" : "No. 9 Sprockets", + "quantity" : 12, + "unitPrice" : 1.23 +}, { + "item" : "Widget (10mm)", + "quantity" : 4, + "unitPrice" : 3.45 +} ] \ No newline at end of file diff --git a/jackson-2/src/test/java/com/baeldung/jackson/csv/CsvUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/csv/CsvUnitTest.java new file mode 100644 index 0000000000..60c8ce79f3 --- /dev/null +++ b/jackson-2/src/test/java/com/baeldung/jackson/csv/CsvUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.jackson.csv; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.common.io.Files; + + +public class CsvUnitTest { + + @Test + public void givenJsonInput_thenWriteCsv() throws JsonParseException, JsonMappingException, IOException { + JsonCsvConverter.JsonToCsv(new File("src/main/resources/orderLines.json"), + new File("src/main/resources/csvFromJson.csv")); + + assertEquals(readFile("src/main/resources/csvFromJson.csv"), + readFile("src/test/resources/expectedCsvFromJson.csv")); + } + + @Test + public void givenCsvInput_thenWritesJson() throws JsonParseException, JsonMappingException, IOException { + JsonCsvConverter.csvToJson(new File("src/main/resources/orderLines.csv"), + new File("src/main/resources/jsonFromCsv.json")); + + assertEquals(readFile("src/main/resources/jsonFromCsv.json"), + readFile("src/test/resources/expectedJsonFromCsv.json")); + + } + + @Test + public void givenJsonInput_thenWriteFormattedCsvOutput() throws JsonParseException, JsonMappingException, IOException { + JsonCsvConverter.JsonToFormattedCsv(new File("src/main/resources/orderLines.json"), + new File("src/main/resources/formattedCsvFromJson.csv")); + + assertEquals(readFile("src/main/resources/formattedCsvFromJson.csv"), + readFile("src/test/resources/expectedFormattedCsvFromJson.csv")); + + } + + private List readFile(String filename) throws IOException { + return Files.readLines(new File(filename), Charset.forName("utf-8")); + } + + +} +; \ No newline at end of file diff --git a/jackson-2/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java new file mode 100644 index 0000000000..b5940a7bd7 --- /dev/null +++ b/jackson-2/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()); + + } +} diff --git a/jackson-2/src/test/java/com/baeldung/jackson/json/compare/JsonCompareUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/json/compare/JsonCompareUnitTest.java new file mode 100644 index 0000000000..03d7c63e36 --- /dev/null +++ b/jackson-2/src/test/java/com/baeldung/jackson/json/compare/JsonCompareUnitTest.java @@ -0,0 +1,126 @@ +package com.baeldung.jackson.json.compare; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Comparator; + +import org.junit.Test; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.TextNode; + +public class JsonCompareUnitTest { + + @Test + public void givenTwoSameJsonDataObjects_whenCompared_thenAreEqual() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + String s1 = "{\"employee\": {\"id\": \"1212\",\"fullName\": \"John Miles\", \"age\": 34 }}"; + String s2 = "{\"employee\": {\"id\": \"1212\",\"age\": 34, \"fullName\": \"John Miles\" }}"; + + JsonNode actualObj1 = mapper.readTree(s1); + JsonNode actualObj2 = mapper.readTree(s2); + + assertEquals(actualObj1, actualObj2); + + } + + @Test + public void givenTwoSameNestedJsonDataObjects_whenCompared_thenEqual() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + String s1 = "{\"employee\": {\"id\": \"1212\",\"fullName\": \"John Miles\",\"age\": 34, \"contact\":{\"email\": \"john@xyz.com\",\"phone\": \"9999999999\"} }}"; + String s2 = "{\"employee\": {\"id\": \"1212\",\"fullName\": \"John Miles\",\"age\": 34, \"contact\":{\"email\": \"john@xyz.com\",\"phone\": \"9999999999\"} }}"; + + JsonNode actualObj1 = mapper.readTree(s1); + JsonNode actualObj2 = mapper.readTree(s2); + + assertEquals(actualObj1, actualObj2); + + } + + @Test + public void givenTwoSameListJsonDataObjects_whenCompared_thenEqual() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + String s1 = "{\"employee\": {\"id\": \"1212\",\"fullName\": \"John Miles\",\"age\": 34, \"skills\":[\"Java\", \"C++\", \"Python\"] }}"; + String s2 = "{\"employee\": {\"id\": \"1212\",\"fullName\": \"John Miles\",\"age\": 34, \"skills\":[\"Java\", \"C++\", \"Python\"] }}"; + + JsonNode actualObj1 = mapper.readTree(s1); + JsonNode actualObj2 = mapper.readTree(s2); + + assertEquals(actualObj1, actualObj2); + + } + + @Test + public void givenTwoJsonDataObjects_whenComparedUsingCustomNumericNodeComparator_thenEqual() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + String s1 = "{\"name\": \"John\",\"score\":5.0}"; + String s2 = "{\"name\": \"John\",\"score\":5}"; + JsonNode actualObj1 = mapper.readTree(s1); + JsonNode actualObj2 = mapper.readTree(s2); + + NumericNodeComparator cmp = new NumericNodeComparator(); + + assertNotEquals(actualObj1, actualObj2); + assertTrue(actualObj1.equals(cmp, actualObj2)); + + } + + public class NumericNodeComparator implements Comparator { + @Override + public int compare(JsonNode o1, JsonNode o2) { + if (o1.equals(o2)) { + return 0; + } + if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)) { + Double d1 = ((NumericNode) o1).asDouble(); + Double d2 = ((NumericNode) o2).asDouble(); + if (d1.compareTo(d2) == 0) { + return 0; + } + } + return 1; + } + } + + @Test + public void givenTwoJsonDataObjects_whenComparedUsingCustomTextNodeComparator_thenEqual() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + String s1 = "{\"name\": \"JOHN\",\"score\":5}"; + String s2 = "{\"name\": \"John\",\"score\":5}"; + JsonNode actualObj1 = mapper.readTree(s1); + JsonNode actualObj2 = mapper.readTree(s2); + + TextNodeComparator cmp = new TextNodeComparator(); + + assertNotEquals(actualObj1, actualObj2); + assertTrue(actualObj1.equals(cmp, actualObj2)); + + } + + public class TextNodeComparator implements Comparator { + @Override + public int compare(JsonNode o1, JsonNode o2) { + if (o1.equals(o2)) { + return 0; + } + if ((o1 instanceof TextNode) && (o2 instanceof TextNode)) { + String s1 = ((TextNode) o1).asText(); + String s2 = ((TextNode) o2).asText(); + if (s1.equalsIgnoreCase(s2)) { + return 0; + } + } + return 1; + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java b/jackson-2/src/test/java/com/baeldung/jackson/node/ExampleStructure.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/ExampleStructure.java diff --git a/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java new file mode 100644 index 0000000000..05426fc844 --- /dev/null +++ b/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.jackson.node; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import com.fasterxml.jackson.databind.JsonNode; + +public class JsonNodeIteratorUnitTest { + + private JsonNodeIterator onTest = new JsonNodeIterator(); + private static String expectedYaml = "name: \n" + + " first: Tatu\n" + + " last: Saloranta\n" + + "title: Jackson founder\n" + + "company: FasterXML\n" + + "pets: \n" + + "- type: dog\n" + + " number: 1\n" + + "- type: fish\n" + + " number: 50"; + +@Test +public void givenANodeTree_whenIteratingSubNodes_thenWeFindExpected() throws IOException { + final JsonNode rootNode = ExampleStructure.getExampleRoot(); + + String yaml = onTest.toYaml(rootNode); + System.out.println(yaml.toString()); + + assertEquals(expectedYaml, yaml); + +} + + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java b/jackson-2/src/test/java/com/baeldung/jackson/node/NodeBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/NodeBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java diff --git a/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java new file mode 100644 index 0000000000..3ed84db60e --- /dev/null +++ b/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.jackson.yaml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.jackson.entities.Order; +import com.baeldung.jackson.entities.OrderLine; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature; + +public class YamlUnitTest { + private ObjectMapper mapper; + + @Before + public void setup() { + mapper = new ObjectMapper(new YAMLFactory().disable(Feature.WRITE_DOC_START_MARKER)); + mapper.findAndRegisterModules(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + } + + @Test + public void givenYamlInput_ObjectCreated() throws JsonParseException, JsonMappingException, IOException { + Order order = mapper.readValue(new File("src/main/resources/orderInput.yaml"), Order.class); + assertEquals("A001", order.getOrderNo()); + assertEquals(LocalDate.parse("2019-04-17", DateTimeFormatter.ISO_DATE), order.getDate()); + assertEquals("Customer, Joe", order.getCustomerName()); + assertEquals(2, order.getOrderLines() + .size()); + } + + @Test + public void givenYamlObject_FileWritten() throws JsonGenerationException, JsonMappingException, IOException { + List lines = new ArrayList<>(); + lines.add(new OrderLine("Copper Wire (200ft)", 1, new BigDecimal(50.67).setScale(2, RoundingMode.HALF_UP))); + lines.add(new OrderLine("Washers (1/4\")", 24, new BigDecimal(.15).setScale(2, RoundingMode.HALF_UP))); + Order order = new Order( + "B-9910", + LocalDate.parse("2019-04-18", DateTimeFormatter.ISO_DATE), + "Customer, Jane", + lines); + mapper.writeValue(new File("src/main/resources/orderOutput.yaml"), order); + + File outputYaml = new File("src/main/resources/orderOutput.yaml"); + assertTrue(outputYaml.exists()); + } +} diff --git a/jackson-2/src/test/resources/expectedCsvFromJson.csv b/jackson-2/src/test/resources/expectedCsvFromJson.csv new file mode 100644 index 0000000000..e15e12f2bf --- /dev/null +++ b/jackson-2/src/test/resources/expectedCsvFromJson.csv @@ -0,0 +1,3 @@ +item,quantity,unitPrice +"No. 9 Sprockets",12,1.23 +"Widget (10mm)",4,3.45 diff --git a/jackson-2/src/test/resources/expectedFormattedCsvFromJson.csv b/jackson-2/src/test/resources/expectedFormattedCsvFromJson.csv new file mode 100644 index 0000000000..5a60ba602a --- /dev/null +++ b/jackson-2/src/test/resources/expectedFormattedCsvFromJson.csv @@ -0,0 +1,3 @@ +count,name +12,"No. 9 Sprockets" +4,"Widget (10mm)" diff --git a/jackson-2/src/test/resources/expectedJsonFromCsv.json b/jackson-2/src/test/resources/expectedJsonFromCsv.json new file mode 100644 index 0000000000..64f18e1673 --- /dev/null +++ b/jackson-2/src/test/resources/expectedJsonFromCsv.json @@ -0,0 +1,9 @@ +[ { + "item" : "No. 9 Sprockets", + "quantity" : 12, + "unitPrice" : 1.23 +}, { + "item" : "Widget (10mm)", + "quantity" : 4, + "unitPrice" : 3.45 +} ] \ No newline at end of file diff --git a/jackson-2/src/test/resources/node_example.json b/jackson-2/src/test/resources/node_example.json new file mode 100644 index 0000000000..d57c1df6e3 --- /dev/null +++ b/jackson-2/src/test/resources/node_example.json @@ -0,0 +1,18 @@ +{ + "name": { + "first": "Tatu", + "last": "Saloranta" + }, + "title": "Jackson founder", + "company": "FasterXML", + "pets": [ + { + "type": "dog", + "number": 1 + }, + { + "type": "fish", + "number": 50 + } + ] +} \ No newline at end of file diff --git a/jackson-simple/.gitignore b/jackson-simple/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/jackson-simple/.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-simple/README.md b/jackson-simple/README.md new file mode 100644 index 0000000000..be647e22d5 --- /dev/null +++ b/jackson-simple/README.md @@ -0,0 +1,13 @@ +========= +### Jackson Articles that are also part of the e-book + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization) +- [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties) +- [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations) +- [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial) +- [Ignore Null Fields with Jackson](http://www.baeldung.com/jackson-ignore-null-fields) +- [Jackson – Change Name of Field](http://www.baeldung.com/jackson-name-of-property) diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml new file mode 100644 index 0000000000..5023ad87b6 --- /dev/null +++ b/jackson-simple/pom.xml @@ -0,0 +1,131 @@ + + 4.0.0 + jackson-simple + 0.1-SNAPSHOT + jackson-simple + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + + commons-io + commons-io + ${commons-io.version} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson.version} + + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + ${jackson.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${jackson.version} + + + + joda-time + joda-time + ${joda-time.version} + + + + com.google.code.gson + gson + ${gson.version} + + + + + + io.rest-assured + json-schema-validator + ${rest-assured.version} + test + + + + io.rest-assured + json-path + ${rest-assured.version} + test + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + jackson-simple + + + src/main/resources + true + + + + + + + 3.8 + 2.10 + 2.8.5 + 4.2 + + + 3.1.1 + 3.11.0 + + + diff --git a/jackson-simple/src/main/resources/logback.xml b/jackson-simple/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/jackson-simple/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/annotation/AliasBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/AliasBean.java new file mode 100644 index 0000000000..1842b2b6f5 --- /dev/null +++ b/jackson-simple/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/annotation/BeanWithCreator.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/MyBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/MyBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/RawBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/RawBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/Zoo.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/Zoo.java diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java new file mode 100644 index 0000000000..25de4a8f7a --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java @@ -0,0 +1,21 @@ +package com.baeldung.jackson.bidirection; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") +public class ItemWithIdentity { + public int id; + public String itemName; + public UserWithIdentity owner; + + public ItemWithIdentity() { + super(); + } + + public ItemWithIdentity(final int id, final String itemName, final UserWithIdentity owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java new file mode 100644 index 0000000000..910ccec174 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java @@ -0,0 +1,17 @@ +package com.baeldung.jackson.bidirection; + +public class ItemWithIgnore { + public int id; + public String itemName; + public UserWithIgnore owner; + + public ItemWithIgnore() { + super(); + } + + public ItemWithIgnore(final int id, final String itemName, final UserWithIgnore owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java new file mode 100644 index 0000000000..0ca8d721e8 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java @@ -0,0 +1,21 @@ +package com.baeldung.jackson.bidirection; + +import com.fasterxml.jackson.annotation.JsonManagedReference; + +public class ItemWithRef { + public int id; + public String itemName; + + @JsonManagedReference + public UserWithRef owner; + + public ItemWithRef() { + super(); + } + + public ItemWithRef(final int id, final String itemName, final UserWithRef owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java new file mode 100644 index 0000000000..db83a09389 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java @@ -0,0 +1,28 @@ +package com.baeldung.jackson.bidirection; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") +public class UserWithIdentity { + public int id; + public String name; + public List userItems; + + public UserWithIdentity() { + super(); + } + + public UserWithIdentity(final int id, final String name) { + this.id = id; + this.name = name; + userItems = new ArrayList(); + } + + public void addItem(final ItemWithIdentity item) { + userItems.add(item); + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java new file mode 100644 index 0000000000..857a373cc5 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java @@ -0,0 +1,28 @@ +package com.baeldung.jackson.bidirection; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class UserWithIgnore { + public int id; + public String name; + + @JsonIgnore + public List userItems; + + public UserWithIgnore() { + super(); + } + + public UserWithIgnore(final int id, final String name) { + this.id = id; + this.name = name; + userItems = new ArrayList(); + } + + public void addItem(final ItemWithIgnore item) { + userItems.add(item); + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java new file mode 100644 index 0000000000..3de03fc651 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java @@ -0,0 +1,28 @@ +package com.baeldung.jackson.bidirection; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonBackReference; + +public class UserWithRef { + public int id; + public String name; + + @JsonBackReference + public List userItems; + + public UserWithRef() { + super(); + } + + public UserWithRef(final int id, final String name) { + this.id = id; + this.name = name; + userItems = new ArrayList(); + } + + public void addItem(final ItemWithRef item) { + userItems.add(item); + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java new file mode 100644 index 0000000000..90c7d9fbac --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.date; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class CustomDateDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -5451717385630622729L; + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + public CustomDateDeserializer() { + this(null); + } + + public CustomDateDeserializer(final Class vc) { + super(vc); + } + + @Override + public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { + final String date = jsonparser.getText(); + try { + return formatter.parse(date); + } catch (final ParseException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java similarity index 55% rename from jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java rename to jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java index 131f4f3695..d840e1940f 100644 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java +++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java @@ -1,34 +1,29 @@ -package com.baeldung.jackson.serialization.jsonserialize; +package com.baeldung.jackson.date; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; 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"); + private static final long serialVersionUID = -2894356342227378312L; + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateSerializer() { this(null); } - public CustomDateSerializer(Class t) { + public CustomDateSerializer(final Class t) { super(t); } @Override - public void serialize(Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { + public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { gen.writeString(formatter.format(value)); } } diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java new file mode 100644 index 0000000000..607e694cef --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java @@ -0,0 +1,29 @@ +package com.baeldung.jackson.date; + +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; + +public class EventWithFormat { + public String name; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") + public Date eventDate; + + public EventWithFormat() { + super(); + } + + public EventWithFormat(final String name, final Date eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public Date getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java new file mode 100644 index 0000000000..c359b5c846 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.date; + +import java.util.Date; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class EventWithSerializer { + public String name; + + @JsonDeserialize(using = CustomDateDeserializer.class) + @JsonSerialize(using = CustomDateSerializer.class) + public Date eventDate; + + public EventWithSerializer() { + super(); + } + + public EventWithSerializer(final String name, final Date eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public Date getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java b/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java new file mode 100644 index 0000000000..eaba9a7173 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java @@ -0,0 +1,41 @@ +package com.baeldung.jackson.deserialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.ItemWithSerializer; +import com.baeldung.jackson.dtos.User; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.node.IntNode; + +public class ItemDeserializerOnClass extends StdDeserializer { + + private static final long serialVersionUID = 5579141241817332594L; + + public ItemDeserializerOnClass() { + this(null); + } + + public ItemDeserializerOnClass(final Class vc) { + super(vc); + } + + /** + * {"id":1,"itemNr":"theItem","owner":2} + */ + @Override + public ItemWithSerializer deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { + final JsonNode node = jp.getCodec() + .readTree(jp); + final int id = (Integer) ((IntNode) node.get("id")).numberValue(); + final String itemName = node.get("itemName") + .asText(); + final int userId = (Integer) ((IntNode) node.get("owner")).numberValue(); + + return new ItemWithSerializer(id, itemName, new User(userId, null)); + } + +} \ No newline at end of file diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java new file mode 100644 index 0000000000..6fce2bc88e --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.dtos; + +public class Item { + public int id; + public String itemName; + public User owner; + + public Item() { + super(); + } + + public Item(final int id, final String itemName, final User owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } + + // API + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public User getOwner() { + return owner; + } + +} \ No newline at end of file diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java new file mode 100644 index 0000000000..aea9aa770d --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.dtos; + +import com.baeldung.jackson.deserialization.ItemDeserializerOnClass; +import com.baeldung.jackson.serialization.ItemSerializerOnClass; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonSerialize(using = ItemSerializerOnClass.class) +@JsonDeserialize(using = ItemDeserializerOnClass.class) +public class ItemWithSerializer { + public final int id; + public final String itemName; + public final User owner; + + public ItemWithSerializer(final int id, final String itemName, final User owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } + + // API + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public User getOwner() { + return owner; + } + +} \ No newline at end of file diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java new file mode 100644 index 0000000000..49cf07baea --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java @@ -0,0 +1,54 @@ +package com.baeldung.jackson.dtos; + +public class MyDto { + + private String stringValue; + private int intValue; + private boolean booleanValue; + + public MyDto() { + super(); + } + + public MyDto(final String stringValue, final int intValue, final boolean booleanValue) { + super(); + + this.stringValue = stringValue; + this.intValue = intValue; + this.booleanValue = booleanValue; + } + + // API + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(final String stringValue) { + this.stringValue = stringValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(final int intValue) { + this.intValue = intValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public void setBooleanValue(final boolean booleanValue) { + this.booleanValue = booleanValue; + } + + // + + @Override + public String toString() { + return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]"; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java new file mode 100644 index 0000000000..2418e8070d --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java @@ -0,0 +1,26 @@ +package com.baeldung.jackson.dtos; + +public class User { + public int id; + public String name; + + public User() { + super(); + } + + public User(final int id, final String name) { + this.id = id; + this.name = name; + } + + // API + + public int getId() { + return id; + } + + public String getName() { + return name; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java new file mode 100644 index 0000000000..69c476d8a5 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java @@ -0,0 +1,29 @@ +package com.baeldung.jackson.dtos.withEnum; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum DistanceEnumWithValue { + KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001); + + private String unit; + private final double meters; + + private DistanceEnumWithValue(String unit, double meters) { + this.unit = unit; + this.meters = meters; + } + + @JsonValue + public double getMeters() { + return meters; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + +} \ No newline at end of file diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java new file mode 100644 index 0000000000..d879c16e6a --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java @@ -0,0 +1,18 @@ +package com.baeldung.jackson.exception; + +import com.fasterxml.jackson.annotation.JsonRootName; + +@JsonRootName(value = "user") +public class UserWithRoot { + public int id; + public String name; + + public UserWithRoot() { + super(); + } + + public UserWithRoot(final int id, final String name) { + this.id = id; + this.name = name; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java new file mode 100644 index 0000000000..bf8c85efba --- /dev/null +++ b/jackson-simple/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-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java new file mode 100644 index 0000000000..26d20d4847 --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.jsonview; + +import com.fasterxml.jackson.annotation.JsonView; + +public class Item { + @JsonView(Views.Public.class) + public int id; + + @JsonView(Views.Public.class) + public String itemName; + + @JsonView(Views.Internal.class) + public String ownerName; + + public Item() { + super(); + } + + public Item(final int id, final String itemName, final String ownerName) { + this.id = id; + this.itemName = itemName; + this.ownerName = ownerName; + } + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public String getOwnerName() { + return ownerName; + } +} diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java new file mode 100644 index 0000000000..65950b7f9f --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java @@ -0,0 +1,9 @@ +package com.baeldung.jackson.jsonview; + +public class Views { + public static class Public { + } + + public static class Internal extends Public { + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java rename to jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java new file mode 100644 index 0000000000..1fdf44e17c --- /dev/null +++ b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.serialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.ItemWithSerializer; +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; + +public class ItemSerializerOnClass extends StdSerializer { + + private static final long serialVersionUID = -1760959597313610409L; + + public ItemSerializerOnClass() { + this(null); + } + + public ItemSerializerOnClass(final Class t) { + super(t); + } + + @Override + public final void serialize(final ItemWithSerializer value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeNumberField("id", value.id); + jgen.writeStringField("itemName", value.itemName); + jgen.writeNumberField("owner", value.owner.id); + jgen.writeEndObject(); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java rename to jackson-simple/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java similarity index 91% rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java index 935777bad1..ee11f8f20e 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java +++ b/jackson-simple/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; @@ -36,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; @@ -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,45 @@ public class JacksonAnnotationUnitTest { assertThat(result, containsString("1")); assertThat(result, containsString("name")); } + + @Test + public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException { + + // arrange + String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}"; + + // act + AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json); + + // assert + 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 + + + */ + + } + + } diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java diff --git a/jackson-simple/src/test/resources/.gitignore b/jackson-simple/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/jackson-simple/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/jackson/README.md b/jackson/README.md index 04e88d0ea1..01d9419a27 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -6,34 +6,30 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization) - [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) - [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) -- [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) +- [Jackson – Decide What Fields Get Serialized/Deserialized](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) - [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson) -- [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial) - [XML Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-xml-serialization-and-deserialization) - [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) - [How To Serialize Enums as JSON Objects with Jackson](http://www.baeldung.com/jackson-serialize-enums) - [Jackson – Marshall String to JsonNode](http://www.baeldung.com/jackson-json-to-jsonnode) -- [Ignore Null Fields with Jackson](http://www.baeldung.com/jackson-ignore-null-fields) - [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) -- [Jackson – Change Name of Field](http://www.baeldung.com/jackson-name-of-property) - [Serialize Only Fields that meet a Custom Criteria with Jackson](http://www.baeldung.com/jackson-serialize-field-custom-criteria) - [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) + 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/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonAnySetter.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonAnySetter.java new file mode 100644 index 0000000000..13c21e37af --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonAnySetter.java @@ -0,0 +1,39 @@ +package com.baeldung.jackson.deserialization.dynamicobject; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnySetter; + +public class ProductJsonAnySetter { + + private String name; + private String category; + private Map details = new LinkedHashMap<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Map getDetails() { + return details; + } + + @JsonAnySetter + public void setDetail(String key, Object value) { + details.put(key, value); + } + +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonNode.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonNode.java new file mode 100644 index 0000000000..729d542df3 --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductJsonNode.java @@ -0,0 +1,35 @@ +package com.baeldung.jackson.deserialization.dynamicobject; + +import com.fasterxml.jackson.databind.JsonNode; + +public class ProductJsonNode { + + private String name; + private String category; + private JsonNode details; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public JsonNode getDetails() { + return details; + } + + public void setDetails(JsonNode details) { + this.details = details; + } + +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductMap.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductMap.java new file mode 100644 index 0000000000..65d225f49b --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/dynamicobject/ProductMap.java @@ -0,0 +1,35 @@ +package com.baeldung.jackson.deserialization.dynamicobject; + +import java.util.Map; + +public class ProductMap { + + private String name; + private String category; + private Map details; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java new file mode 100644 index 0000000000..44b10ee39b --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Employee { + + private final long id; + private final String name; + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public Employee(@JsonProperty("id") long id, @JsonProperty("name") String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java new file mode 100644 index 0000000000..d9041720b6 --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java @@ -0,0 +1,44 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +@JsonDeserialize(builder = Person.Builder.class) +public class Person { + + private final String name; + private final Integer age; + + private Person(String name, Integer age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } + + @JsonPOJOBuilder + static class Builder { + String name; + Integer age; + + Builder withName(String name) { + this.name = name; + return this; + } + + Builder withAge(Integer age) { + this.age = age; + return this; + } + + Person build() { + return new Person(name, age); + } + } +} 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/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/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/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/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/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/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 c6ebfd10fb..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("writer") -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/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/main/resources/node_example.json b/jackson/src/main/resources/node_example.json deleted file mode 100644 index 69d37efbf6..0000000000 --- a/jackson/src/main/resources/node_example.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": - { - "first": "Tatu", - "last": "Saloranta" - }, - - "title": "Jackson founder", - "company": "FasterXML" -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/dynamicobject/DynamicObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/dynamicobject/DynamicObjectDeserializationUnitTest.java new file mode 100644 index 0000000000..d49677c1a2 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/dynamicobject/DynamicObjectDeserializationUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.jackson.deserialization.dynamicobject; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.util.Scanner; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class DynamicObjectDeserializationUnitTest { + + private ObjectMapper objectMapper; + + @BeforeEach + void setup() { + objectMapper = new ObjectMapper(); + } + + private String readResource(String path) { + try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path), "UTF-8")) { + return scanner.useDelimiter("\\A").next(); + } + } + + @Test + void givenJsonString_whenParsingToJsonNode_thenItMustContainDynamicProperties() throws JsonParseException, JsonMappingException, IOException { + // given + String json = readResource("/deserialize-dynamic-object/embedded.json"); + + // when + ProductJsonNode product = objectMapper.readValue(json, ProductJsonNode.class); + + // then + assertThat(product.getName()).isEqualTo("Pear yPhone 72"); + assertThat(product.getDetails().get("audioConnector").asText()).isEqualTo("none"); + } + + @Test + void givenJsonString_whenParsingToMap_thenItMustContainDynamicProperties() throws JsonParseException, JsonMappingException, IOException { + // given + String json = readResource("/deserialize-dynamic-object/embedded.json"); + + // when + ProductMap product = objectMapper.readValue(json, ProductMap.class); + + // then + assertThat(product.getName()).isEqualTo("Pear yPhone 72"); + assertThat(product.getDetails().get("audioConnector")).isEqualTo("none"); + } + + @Test + void givenJsonString_whenParsingWithJsonAnySetter_thenItMustContainDynamicProperties() throws JsonParseException, JsonMappingException, IOException { + // given + String json = readResource("/deserialize-dynamic-object/flat.json"); + + // when + ProductJsonAnySetter product = objectMapper.readValue(json, ProductJsonAnySetter.class); + + // then + assertThat(product.getName()).isEqualTo("Pear yPhone 72"); + assertThat(product.getDetails().get("audioConnector")).isEqualTo("none"); + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java new file mode 100644 index 0000000000..1252179e3a --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class ImmutableObjectDeserializationUnitTest { + + @Test + public void whenPublicConstructorIsUsed_thenObjectIsDeserialized() throws IOException { + final String json = "{\"name\":\"Frank\",\"id\":5000}"; + Employee employee = new ObjectMapper().readValue(json, Employee.class); + + assertEquals("Frank", employee.getName()); + assertEquals(5000, employee.getId()); + } + + @Test + public void whenBuilderIsUsedAndFieldIsNull_thenObjectIsDeserialized() throws IOException { + final String json = "{\"name\":\"Frank\"}"; + Person person = new ObjectMapper().readValue(json, Person.class); + + assertEquals("Frank", person.getName()); + assertNull(person.getAge()); + } + + @Test + public void whenBuilderIsUsedAndAllFieldsPresent_thenObjectIsDeserialized() throws IOException { + final String json = "{\"name\":\"Frank\",\"age\":50}"; + Person person = new ObjectMapper().readValue(json, Person.class); + + assertEquals("Frank", person.getName()); + assertEquals(50, (int) person.getAge()); + } +} 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/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/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 deleted file mode 100644 index 1bcde998d6..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\",\"authors\":[{\"id\":\"9bcd817d-0141-42e6-8f04-e5aaab0980b6\",\"firstName\":\"Joshua\",\"lastName\":\"Bloch\"}],\"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/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/dtos/Address.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java new file mode 100644 index 0000000000..985851f456 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java @@ -0,0 +1,33 @@ +package com.baeldung.jackson.dtos; + +public class Address { + + String streetNumber; + String streetName; + 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..13093cdcad --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java @@ -0,0 +1,47 @@ +package com.baeldung.jackson.dtos; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JacksonXmlRootElement(localName = "person") +public final class Person { + private String firstName; + private String lastName; + private List phoneNumbers = new ArrayList<>(); + 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/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/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/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/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/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/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/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/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 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/JacksonDateUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java index 390030d0d4..672ff5c6fd 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java @@ -11,7 +11,6 @@ import java.time.LocalDateTime; import java.util.Date; import java.util.TimeZone; -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.Test; @@ -24,8 +23,9 @@ import com.baeldung.jackson.date.EventWithSerializer; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.util.StdDateFormat; import com.fasterxml.jackson.datatype.joda.JodaModule; -import com.fasterxml.jackson.datatype.jsr310.JSR310Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class JacksonDateUnitTest { @@ -54,10 +54,12 @@ public class JacksonDateUnitTest { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.setDateFormat(new ISO8601DateFormat()); + + // StdDateFormat is ISO8601 since jackson 2.9 + mapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true)); final String result = mapper.writeValueAsString(event); - assertThat(result, containsString("1970-01-01T02:30:00Z")); + assertThat(result, containsString("1970-01-01T02:30:00.000+00:00")); } @Test @@ -152,7 +154,7 @@ public class JacksonDateUnitTest { final LocalDateTime date = LocalDateTime.of(2014, 12, 20, 2, 30); final ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JSR310Module()); + mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); final String result = mapper.writeValueAsString(date); diff --git a/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java index 6be2f29baa..e783c67f5b 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java @@ -12,8 +12,6 @@ import org.junit.runners.Suite; ,JacksonDeserializationUnitTest.class ,JacksonDeserializationUnitTest.class ,JacksonPrettyPrintUnitTest.class - ,JacksonSerializationIgnoreUnitTest.class - ,JacksonSerializationUnitTest.class ,SandboxUnitTest.class ,JacksonFieldUnitTest.class }) // @formatter:on 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..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,19 +2,25 @@ 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; 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,24 +55,76 @@ 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. - 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); } + @Test + public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + + String xml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person value = xmlMapper.readValue(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(); + + String expectedXml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + + Person person = new Person(); + + person.setFirstName("Rohan"); + person.setLastName("Daye"); + + List ph = new ArrayList<>(); + ph.add("9911034731"); + ph.add("9911033478"); + person.setPhoneNumbers(ph); + + List
addresses = new ArrayList<>(); + + Address address1 = new Address(); + address1.setStreetNumber("1"); + address1.setStreetName("Name1"); + address1.setCity("City1"); + + Address address2 = new Address(); + address2.setStreetNumber("2"); + address2.setStreetName("Name2"); + address2.setCity("City2"); + + addresses.add(address1); + addresses.add(address2); + + person.setAddress(addresses); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + xmlMapper.writeValue(byteArrayOutputStream, person); + assertEquals(expectedXml, byteArrayOutputStream.toString()); + } + private static String inputStreamToString(InputStream is) throws IOException { BufferedReader br; StringBuilder sb = new StringBuilder(); @@ -103,10 +161,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/deserialize-dynamic-object/embedded.json b/jackson/src/test/resources/deserialize-dynamic-object/embedded.json new file mode 100644 index 0000000000..e4f11f7f1f --- /dev/null +++ b/jackson/src/test/resources/deserialize-dynamic-object/embedded.json @@ -0,0 +1,8 @@ +{ + "name": "Pear yPhone 72", + "category": "cellphone", + "details": { + "displayAspectRatio": "97:3", + "audioConnector": "none" + } +} \ No newline at end of file diff --git a/jackson/src/test/resources/deserialize-dynamic-object/flat.json b/jackson/src/test/resources/deserialize-dynamic-object/flat.json new file mode 100644 index 0000000000..799ea9339d --- /dev/null +++ b/jackson/src/test/resources/deserialize-dynamic-object/flat.json @@ -0,0 +1,6 @@ +{ + "name": "Pear yPhone 72", + "category": "cellphone", + "displayAspectRatio": "97:3", + "audioConnector": "none" +} \ No newline at end of file diff --git a/java-collections-conversions/README.md b/java-collections-conversions/README.md index 0f89e07d63..614f20f186 100644 --- a/java-collections-conversions/README.md +++ b/java-collections-conversions/README.md @@ -10,3 +10,7 @@ - [Converting a List to String in Java](http://www.baeldung.com/java-list-to-string) - [How to Convert List to Map in Java](http://www.baeldung.com/java-list-to-map) - [Array to String Conversions](https://www.baeldung.com/java-array-to-string) +- [Converting a Collection to ArrayList in Java](https://www.baeldung.com/java-convert-collection-arraylist) +- [Java 8 Collectors toMap](https://www.baeldung.com/java-collectors-tomap) +- [Converting Iterable to Collection in Java](https://www.baeldung.com/java-iterable-to-collection) +- [Converting Iterator to List](https://www.baeldung.com/java-convert-iterator-to-list) diff --git a/java-collections-conversions/pom.xml b/java-collections-conversions/pom.xml index 9b54652001..ee7221b25e 100644 --- a/java-collections-conversions/pom.xml +++ b/java-collections-conversions/pom.xml @@ -3,8 +3,8 @@ 4.0.0 java-collections-conversions 0.1.0-SNAPSHOT - jar java-collections-conversions + jar com.baeldung diff --git a/java-collections-conversions/src/main/java/com/baeldung/convertToMap/Book.java b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/Book.java new file mode 100644 index 0000000000..847e0bd8cd --- /dev/null +++ b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/Book.java @@ -0,0 +1,48 @@ +package com.baeldung.convertToMap; + +public class Book { + private String name; + private int releaseYear; + private String isbn; + + + @Override + public String toString() { + return "Book{" + + "name='" + name + '\'' + + ", releaseYear=" + releaseYear + + ", isbn='" + isbn + '\'' + + '}'; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getReleaseYear() { + return releaseYear; + } + + public void setReleaseYear(int releaseYear) { + this.releaseYear = releaseYear; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public Book(String name, int releaseYear, String isbn) { + this.name = name; + this.releaseYear = releaseYear; + this.isbn = isbn; + } +} + diff --git a/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java new file mode 100644 index 0000000000..e33d9ee212 --- /dev/null +++ b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java @@ -0,0 +1,33 @@ +package com.baeldung.convertToMap; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ConvertToMap { + public Map listToMap(List books) { + return books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName)); + } + + public Map listToMapWithDupKeyError(List books) { + return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity())); + } + + public Map listToMapWithDupKey(List books) { + return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(), (existing, replacement) -> existing)); + } + + public Map listToConcurrentMap(List books) { + return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(), (o1, o2) -> o1, ConcurrentHashMap::new)); + } + + public TreeMap listToSortedMap(List books) { + return books.stream() + .sorted(Comparator.comparing(Book::getName)) + .collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new)); + } + + +} + diff --git a/java-collections-conversions/src/test/java/com/baeldung/convert/iteratortolist/ConvertIteratorToListServiceUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convert/iteratortolist/ConvertIteratorToListServiceUnitTest.java new file mode 100644 index 0000000000..ced2ddcfc0 --- /dev/null +++ b/java-collections-conversions/src/test/java/com/baeldung/convert/iteratortolist/ConvertIteratorToListServiceUnitTest.java @@ -0,0 +1,100 @@ +package com.baeldung.convert.iteratortolist; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.apache.commons.collections4.IteratorUtils; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class ConvertIteratorToListServiceUnitTest { + + Iterator iterator; + + @Before + public void setUp() throws Exception { + iterator = Arrays.asList(1, 2, 3) + .iterator(); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListUsingWhileLoop_thenReturnAList() { + + List actualList = new ArrayList(); + + // Convert Iterator to List using while loop dsf + while (iterator.hasNext()) { + actualList.add(iterator.next()); + } + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListAfterJava8_thenReturnAList() { + List actualList = new ArrayList(); + + // Convert Iterator to List using Java 8 + iterator.forEachRemaining(actualList::add); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListJava8Stream_thenReturnAList() { + + // Convert iterator to iterable + Iterable iterable = () -> iterator; + + // Extract List from stream + List actualList = StreamSupport + .stream(iterable.spliterator(), false) + .collect(Collectors.toList()); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToImmutableListWithGuava_thenReturnAList() { + + // Convert Iterator to an Immutable list using Guava library in Java + List actualList = ImmutableList.copyOf(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToMutableListWithGuava_thenReturnAList() { + + // Convert Iterator to a mutable list using Guava library in Java + List actualList = Lists.newArrayList(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToMutableListWithApacheCommons_thenReturnAList() { + + // Convert Iterator to a mutable list using Apache Commons library in Java + List actualList = IteratorUtils.toList(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } +} diff --git a/java-collections-conversions/src/test/java/com/baeldung/convertToMap/ConvertToMapUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convertToMap/ConvertToMapUnitTest.java new file mode 100644 index 0000000000..d6eab461d7 --- /dev/null +++ b/java-collections-conversions/src/test/java/com/baeldung/convertToMap/ConvertToMapUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.convertToMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + + +public class ConvertToMapUnitTest { + + private List bookList; + private ConvertToMap convertToMap = new ConvertToMap(); + + @Before + public void init() { + bookList = new ArrayList<>(); + bookList.add(new Book("The Fellowship of the Ring", 1954, "0395489318")); + bookList.add(new Book("The Two Towers", 1954, "0345339711")); + bookList.add(new Book("The Return of the King", 1955, "0618129111")); + } + + @Test + public void whenConvertFromListToMap() { + assertTrue(convertToMap.listToMap(bookList).size() == 3); + } + + @Test(expected = IllegalStateException.class) + public void whenMapHasDuplicateKey_without_merge_function_then_runtime_exception() { + convertToMap.listToMapWithDupKeyError(bookList); + } + + @Test + public void whenMapHasDuplicateKeyThenMergeFunctionHandlesCollision() { + Map booksByYear = convertToMap.listToMapWithDupKey(bookList); + assertEquals(2, booksByYear.size()); + assertEquals("0395489318", booksByYear.get(1954).getIsbn()); + } + + @Test + public void whenCreateConcurrentHashMap() { + assertTrue(convertToMap.listToConcurrentMap(bookList) instanceof ConcurrentHashMap); + } + + @Test + public void whenMapisSorted() { + assertTrue(convertToMap.listToSortedMap(bookList).firstKey().equals("The Fellowship of the Ring")); + } +} diff --git a/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java index 5be4121bc7..1de600aebf 100644 --- a/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java +++ b/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java @@ -33,9 +33,6 @@ public class FooUnitTest { srcCollection.add(sam); srcCollection.add(alice); srcCollection.add(buffy); - - // make sure the collection isn't sorted accidentally - assertFalse("Oops: source collection is already sorted!", isSorted(srcCollection)); } /** diff --git a/java-collections-conversions/src/test/java/com/baeldung/java/collections/IterableToCollectionUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/java/collections/IterableToCollectionUnitTest.java new file mode 100644 index 0000000000..0283191b74 --- /dev/null +++ b/java-collections-conversions/src/test/java/com/baeldung/java/collections/IterableToCollectionUnitTest.java @@ -0,0 +1,122 @@ +package com.baeldung.java.collections; + +import static org.hamcrest.Matchers.contains; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.apache.commons.collections4.IterableUtils; +import org.apache.commons.collections4.IteratorUtils; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class IterableToCollectionUnitTest { + + Iterable iterable = Arrays.asList("john", "tom", "jane"); + Iterator iterator = iterable.iterator(); + + @Test + public void whenConvertIterableToListUsingJava_thenSuccess() { + List result = new ArrayList(); + for (String str : iterable) { + result.add(str); + } + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIterableToListUsingJava8_thenSuccess() { + List result = new ArrayList(); + iterable.forEach(result::add); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIterableToListUsingJava8WithSpliterator_thenSuccess() { + List result = StreamSupport.stream(iterable.spliterator(), false) + .collect(Collectors.toList()); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIterableToListUsingGuava_thenSuccess() { + List result = Lists.newArrayList(iterable); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIterableToImmutableListUsingGuava_thenSuccess() { + List result = ImmutableList.copyOf(iterable); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIterableToListUsingApacheCommons_thenSuccess() { + List result = IterableUtils.toList(iterable); + + assertThat(result, contains("john", "tom", "jane")); + } + + // ======================== Iterator + + @Test + public void whenConvertIteratorToListUsingJava_thenSuccess() { + List result = new ArrayList(); + while (iterator.hasNext()) { + result.add(iterator.next()); + } + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIteratorToListUsingJava8_thenSuccess() { + List result = new ArrayList(); + iterator.forEachRemaining(result::add); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIteratorToListUsingJava8WithSpliterator_thenSuccess() { + List result = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) + .collect(Collectors.toList()); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIteratorToListUsingGuava_thenSuccess() { + List result = Lists.newArrayList(iterator); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIteratorToImmutableListUsingGuava_thenSuccess() { + List result = ImmutableList.copyOf(iterator); + + assertThat(result, contains("john", "tom", "jane")); + } + + @Test + public void whenConvertIteratorToListUsingApacheCommons_thenSuccess() { + List result = IteratorUtils.toList(iterator); + + assertThat(result, contains("john", "tom", "jane")); + } +} diff --git a/java-collections-maps-2/README.md b/java-collections-maps-2/README.md new file mode 100644 index 0000000000..ff84e93ce4 --- /dev/null +++ b/java-collections-maps-2/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: +- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives) +- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap) diff --git a/java-collections-maps-2/pom.xml b/java-collections-maps-2/pom.xml new file mode 100644 index 0000000000..5f27eaa2d8 --- /dev/null +++ b/java-collections-maps-2/pom.xml @@ -0,0 +1,61 @@ + + + 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 + ${trove4j.version} + + + it.unimi.dsi + fastutil + ${fastutil.version} + + + colt + colt + ${colt.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + 8.2.0 + 3.0.2 + 8.1.0 + 1.2.0 + 3.8.1 + 3.11.1 + + + \ No newline at end of file diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/CopyHashMap.java b/java-collections-maps-2/src/main/java/com/baeldung/map/CopyHashMap.java new file mode 100644 index 0000000000..2ebc9413c8 --- /dev/null +++ b/java-collections-maps-2/src/main/java/com/baeldung/map/CopyHashMap.java @@ -0,0 +1,55 @@ +package com.baeldung.map; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.SerializationUtils; + +public class CopyHashMap { + + public static HashMap copyUsingConstructor(HashMap originalMap) { + return new HashMap(originalMap); + } + + public static HashMap copyUsingClone(HashMap originalMap) { + return (HashMap) originalMap.clone(); + } + + public static HashMap copyUsingPut(HashMap originalMap) { + HashMap shallowCopy = new HashMap(); + Set> entries = originalMap.entrySet(); + for(Map.Entry mapEntry: entries) { + shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); + } + + return shallowCopy; + } + + public static HashMap copyUsingPutAll(HashMap originalMap) { + HashMap shallowCopy = new HashMap(); + shallowCopy.putAll(originalMap); + + return shallowCopy; + } + + public static HashMap copyUsingJava8Stream(HashMap originalMap) { + Set> entries = originalMap.entrySet(); + HashMap shallowCopy = (HashMap) entries + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return shallowCopy; + } + + public static HashMap shallowCopy(HashMap originalMap) { + return (HashMap) originalMap.clone(); + } + + public static HashMap deepCopy(HashMap originalMap) { + return SerializationUtils.clone(originalMap); + } + +} 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 new file mode 100644 index 0000000000..d835950c68 --- /dev/null +++ b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java @@ -0,0 +1,69 @@ +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.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 { + + public static void main(String[] args) { + + eclipseCollectionsMap(); + troveMap(); + coltMap(); + fastutilMap(); + } + + 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; + } + + private static void coltMap() { + AbstractIntDoubleMap map = new OpenIntDoubleHashMap(); + map.put(1, 4.5); + double value = map.get(1); + } + + private static void eclipseCollectionsMap() { + MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty(); + mutableIntIntMap.addToValue(1, 1); + + ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty(); + + 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}; + + TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); + + 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); + } +} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/CopyHashMapUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/CopyHashMapUnitTest.java new file mode 100644 index 0000000000..c400eea153 --- /dev/null +++ b/java-collections-maps-2/src/test/java/com/baeldung/map/CopyHashMapUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.map; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import com.google.common.collect.ImmutableMap; + +public class CopyHashMapUnitTest { + + @Test + public void givenHashMap_whenShallowCopy_thenCopyisNotSameAsOriginal() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + + HashMap shallowCopy = CopyHashMap.shallowCopy(map); + + assertThat(shallowCopy).isNotSameAs(map); + + } + + @Test + public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + + HashMap shallowCopy = CopyHashMap.shallowCopy(map); + + emp1.setName("Johny"); + + assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1")); + + } + + @Test + public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + HashMap deepCopy = CopyHashMap.deepCopy(map); + + emp1.setName("Johny"); + + assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1")); + + } + + @Test + public void givenImmutableMap_whenCopyUsingGuava_thenCopyShouldNotChange() { + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + + Map map = ImmutableMap. builder() + .put("emp1",emp1) + .put("emp2",emp2) + .build(); + Map shallowCopy = ImmutableMap.copyOf(map); + + assertThat(shallowCopy).isSameAs(map); + + } + +} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/Employee.java b/java-collections-maps-2/src/test/java/com/baeldung/map/Employee.java new file mode 100644 index 0000000000..7963fa811c --- /dev/null +++ b/java-collections-maps-2/src/test/java/com/baeldung/map/Employee.java @@ -0,0 +1,28 @@ +package com.baeldung.map; + +import java.io.Serializable; + +public class Employee implements Serializable{ + + private String name; + + public Employee(String name) { + super(); + this.name = name; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } + +} + + diff --git a/java-collections-maps/README.md b/java-collections-maps/README.md index a6037a3c57..2eeb2c8843 100644 --- a/java-collections-maps/README.md +++ b/java-collections-maps/README.md @@ -17,3 +17,7 @@ - [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max) - [Merging Two Maps with Java 8](https://www.baeldung.com/java-merge-maps) - [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists) +- [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/java-collections-maps/pom.xml b/java-collections-maps/pom.xml index 0803866c51..b5eba31437 100644 --- a/java-collections-maps/pom.xml +++ b/java-collections-maps/pom.xml @@ -3,8 +3,8 @@ 4.0.0 java-collections-maps 0.1.0-SNAPSHOT - jar java-collections-maps + jar com.baeldung @@ -39,7 +39,7 @@ one.util streamex - 0.6.5 + ${streamex.version} @@ -50,5 +50,6 @@ 1.7.0 3.6.1 7.1.0 + 0.6.5 diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java new file mode 100644 index 0000000000..aca0d05ef1 --- /dev/null +++ b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java @@ -0,0 +1,34 @@ +package com.baeldung.convert; + +import com.google.common.base.Joiner; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.stream.Collectors; + +public class MapToString { + + public static String convertWithIteration(Map map) { + StringBuilder mapAsString = new StringBuilder("{"); + for (Integer key : map.keySet()) { + mapAsString.append(key + "=" + map.get(key) + ", "); + } + mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}"); + return mapAsString.toString(); + } + + public static String convertWithStream(Map map) { + String mapAsString = map.keySet().stream() + .map(key -> key + "=" + map.get(key)) + .collect(Collectors.joining(", ", "{", "}")); + return mapAsString; + } + + public static String convertWithGuava(Map map) { + return Joiner.on(",").withKeyValueSeparator("=").join(map); + } + + public static String convertWithApache(Map map) { + return StringUtils.join(map); + } +} diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java new file mode 100644 index 0000000000..caabca4a09 --- /dev/null +++ b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java @@ -0,0 +1,21 @@ +package com.baeldung.convert; + +import com.google.common.base.Splitter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +public class StringToMap { + + public static Map convertWithStream(String mapAsString) { + Map map = Arrays.stream(mapAsString.split(",")) + .map(entry -> entry.split("=")) + .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1])); + return map; + } + + public static Map convertWithGuava(String mapAsString) { + return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString); + } +} diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java new file mode 100644 index 0000000000..d9923e74a0 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.convert; + +import org.apache.commons.collections4.MapUtils; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class MapToStringUnitTest { + + private Map wordsByKey = new HashMap<>(); + + @BeforeEach + public void setup() { + wordsByKey.clear(); + wordsByKey.put(1, "one"); + wordsByKey.put(2, "two"); + wordsByKey.put(3, "three"); + wordsByKey.put(4, "four"); + } + + @Test + public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithIteration(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithStream(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithGuava(wordsByKey); + Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString); + } + + @Test + public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithApache(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + MapUtils.debugPrint(System.out, "Map as String", wordsByKey); + } +} \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java new file mode 100644 index 0000000000..8fb906efd0 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.convert; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class StringToMapUnitTest { + + @Test + public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } + + @Test + void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..b3aaf8925f --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java @@ -0,0 +1,227 @@ +package com.baeldung.java.map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +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; +import org.junit.Test; + +public class MultiValuedMapUnitTest { + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange"); + + } + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutAllMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.putAll("vehicles", Arrays.asList("car", "bike")); + + assertThat((Collection) map.get("vehicles")).containsExactly("car", "bike"); + + } + + @Test + public void givenMultiValuesMap_whenGettingValueUsingGetMethod_thenReturningValue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple"); + } + + @Test + public void givenMultiValuesMap_whenUsingEntriesMethod_thenReturningMappings() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + + Collection> entries = (Collection>) map.entries(); + + for(Map.Entry entry : entries) { + assertThat(entry.getKey()).contains("fruits"); + assertTrue(entry.getValue().equals("apple") || entry.getValue().equals("orange") ); + } + } + + @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"); + + 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"); + + Set keys = map.keySet(); + + assertThat(keys).contains("fruits", "vehicles"); + + } + + @Test + public void givenMultiValuesMap_whenUsingValuesMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMethod_thenReturningUpdatedMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.remove("fruits"); + + assertThat(((Collection) map.values())).contains("car", "bike"); + + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMappingMethod_thenReturningUpdatedMapAfterMappingRemoved() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.removeMapping("fruits", "apple"); + + assertThat(((Collection) map.values())).contains("orange", "car", "bike"); + } + + @Test + public void givenMultiValuesMap_whenUsingClearMethod_thenReturningEmptyMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.clear(); + + assertTrue(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsKeyMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertTrue(map.containsKey("fruits")); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsValueMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertTrue(map.containsValue("orange")); + } + + @Test + public void givenMultiValuesMap_whenUsingIsEmptyMethod_thenReturningFalse() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertFalse(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingSizeMethod_thenReturningElementCount() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertEquals(4, map.size()); + } + + @Test + public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("fruits", "orange"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange", "orange"); + } + + @Test + public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { + MultiValuedMap map = new HashSetValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "apple"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple"); + } + + @Test(expected = UnsupportedOperationException.class) + public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map); + + immutableMap.put("fruits", "banana"); + + } + + +} 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/README.md b/java-dates-2/README.md new file mode 100644 index 0000000000..35286115d4 --- /dev/null +++ b/java-dates-2/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: +- [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar) +- [Convert Time to Milliseconds in Java](https://www.baeldung.com/java-time-milliseconds) diff --git a/java-dates-2/pom.xml b/java-dates-2/pom.xml new file mode 100644 index 0000000000..c1419514ef --- /dev/null +++ b/java-dates-2/pom.xml @@ -0,0 +1,70 @@ + + 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 + + + + + joda-time + joda-time + ${joda-time.version} + + + + + commons-validator + commons-validator + ${commons-validator.version} + + + + + 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 + 2.10 + 1.6 + 1.9 + 1.9 + + diff --git a/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidator.java b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidator.java new file mode 100644 index 0000000000..b774edab43 --- /dev/null +++ b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidator.java @@ -0,0 +1,5 @@ +package com.baeldung.date.validation; + +public interface DateValidator { + boolean isValid(String dateStr); +} diff --git a/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingApacheValidator.java b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingApacheValidator.java new file mode 100644 index 0000000000..f7b2f48d2d --- /dev/null +++ b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingApacheValidator.java @@ -0,0 +1,11 @@ +package com.baeldung.date.validation; + +import org.apache.commons.validator.GenericValidator; + +public class DateValidatorUsingApacheValidator implements DateValidator { + + @Override + public boolean isValid(String dateStr) { + return GenericValidator.isDate(dateStr, "yyyy-MM-dd", true); + } +} diff --git a/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateFormat.java b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateFormat.java new file mode 100644 index 0000000000..eb0fbdb086 --- /dev/null +++ b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateFormat.java @@ -0,0 +1,25 @@ +package com.baeldung.date.validation; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class DateValidatorUsingDateFormat implements DateValidator { + private String dateFormat; + + public DateValidatorUsingDateFormat(String dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public boolean isValid(String dateStr) { + DateFormat sdf = new SimpleDateFormat(this.dateFormat); + sdf.setLenient(false); + try { + sdf.parse(dateStr); + } catch (ParseException e) { + return false; + } + return true; + } +} diff --git a/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatter.java b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatter.java new file mode 100644 index 0000000000..0f68baf06e --- /dev/null +++ b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatter.java @@ -0,0 +1,22 @@ +package com.baeldung.date.validation; + +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateValidatorUsingDateTimeFormatter implements DateValidator { + private DateTimeFormatter dateFormatter; + + public DateValidatorUsingDateTimeFormatter(DateTimeFormatter dateFormatter) { + this.dateFormatter = dateFormatter; + } + + @Override + public boolean isValid(String dateStr) { + try { + this.dateFormatter.parse(dateStr); + } catch (DateTimeParseException e) { + return false; + } + return true; + } +} diff --git a/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingLocalDate.java b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingLocalDate.java new file mode 100644 index 0000000000..f04c2e4185 --- /dev/null +++ b/java-dates-2/src/main/java/com/baeldung/date/validation/DateValidatorUsingLocalDate.java @@ -0,0 +1,23 @@ +package com.baeldung.date.validation; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateValidatorUsingLocalDate implements DateValidator { + private DateTimeFormatter dateFormatter; + + public DateValidatorUsingLocalDate(DateTimeFormatter dateFormatter) { + this.dateFormatter = dateFormatter; + } + + @Override + public boolean isValid(String dateStr) { + try { + LocalDate.parse(dateStr, this.dateFormatter); + } catch (DateTimeParseException e) { + return false; + } + return true; + } +} diff --git a/java-dates-2/src/test/java/com/baeldung/convert/ConvertDateTimeUnitTest.java b/java-dates-2/src/test/java/com/baeldung/convert/ConvertDateTimeUnitTest.java new file mode 100644 index 0000000000..cd31ccc799 --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/convert/ConvertDateTimeUnitTest.java @@ -0,0 +1,59 @@ +package com.baeldung.convert; + +import org.joda.time.Instant; +import org.junit.Assert; +import org.junit.Test; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; + +public class ConvertDateTimeUnitTest { + + public final long millis = 1556175797428L; + + @Test + public void givenLocalDateTime_WhenToEpochMillis_ThenMillis() { + ZoneId id = ZoneId.systemDefault(); + + LocalDateTime localDateTime = + LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(millis), id); + + ZonedDateTime zdt = ZonedDateTime.of(localDateTime, id); + + Assert.assertEquals(millis, zdt.toInstant().toEpochMilli()); + } + + @Test + public void givenJava8Instant_WhenGToEpochMillis_ThenMillis() { + java.time.Instant instant = java.time.Instant.ofEpochMilli(millis); + Assert.assertEquals(millis, instant.toEpochMilli()); + } + + @Test + public void givenDate_WhenGetTime_ThenMillis() { + Date date = new Date(millis); + Assert.assertEquals(millis, date.getTime()); + } + + @Test + public void givenCalendar_WhenGetTimeInMillis_ThenMillis() { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(millis)); + Assert.assertEquals(millis, calendar.getTimeInMillis()); + } + + @Test + public void givenJodaInstant_WhenGetMillis_ThenMillis() { + Instant jodaInstant = Instant.ofEpochMilli(millis); + Assert.assertEquals(millis, jodaInstant.getMillis()); + } + + @Test + public void givenJODADateTime_WhenGetMillis_ThenMillis() { + org.joda.time.DateTime jodaDateTime = new org.joda.time.DateTime(millis); + Assert.assertEquals(millis, jodaDateTime.getMillis()); + } +} diff --git a/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingApacheValidatorUnitTest.java b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingApacheValidatorUnitTest.java new file mode 100644 index 0000000000..daa464722a --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingApacheValidatorUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.date.validation; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.apache.commons.validator.GenericValidator; +import org.junit.Test; + +public class DateValidatorUsingApacheValidatorUnitTest { + + @Test + public void whenValidDatePassed_ThenTrue() { + assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true)); + } + + @Test + public void whenInvalidDatePassed_ThenFalse() { + assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true)); + } +} diff --git a/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateFormatUnitTest.java b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateFormatUnitTest.java new file mode 100644 index 0000000000..9b86b3381c --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateFormatUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.date.validation; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class DateValidatorUsingDateFormatUnitTest { + + @Test + public void givenValidator_whenValidDatePassed_ThenTrue() { + DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); + + assertTrue(validator.isValid("02/28/2019")); + } + + @Test + public void givenValidator_whenInvalidDatePassed_ThenFalse() { + DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); + + assertFalse(validator.isValid("02/30/2019")); + } +} diff --git a/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatterUnitTest.java b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatterUnitTest.java new file mode 100644 index 0000000000..368b04f8e3 --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingDateTimeFormatterUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.date.validation; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.time.format.DateTimeFormatter; +import java.time.format.ResolverStyle; +import java.util.Locale; + +import org.junit.Test; + +public class DateValidatorUsingDateTimeFormatterUnitTest { + + @Test + public void givenValidator_whenValidDatePassed_ThenTrue() { + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.US) + .withResolverStyle(ResolverStyle.STRICT); + DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); + + assertTrue(validator.isValid("2019-02-28")); + } + + @Test + public void givenValidator_whenInValidDatePassed_ThenFalse() { + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.US) + .withResolverStyle(ResolverStyle.STRICT); + DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); + + assertFalse(validator.isValid("2019-02-30")); + } + +} diff --git a/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingLocalDateUnitTest.java b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingLocalDateUnitTest.java new file mode 100644 index 0000000000..63296359db --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/date/validation/DateValidatorUsingLocalDateUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.date.validation; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.time.format.DateTimeFormatter; + +import org.junit.Test; + +public class DateValidatorUsingLocalDateUnitTest { + + @Test + public void givenValidator_whenValidDatePassed_ThenTrue() { + DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; + DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter); + + assertTrue(validator.isValid("20190228")); + } + + @Test + public void givenValidator_whenInValidDatePassed_ThenFalse() { + DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; + DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter); + + assertFalse(validator.isValid("20190230")); + } +} 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..b221c04199 --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java @@ -0,0 +1,36 @@ +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; + +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()); + assertThat(xmlGregorianCalendar.getTimezone()).isEqualTo(DatatypeConstants.FIELD_UNDEFINED); + } + + @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/java-dates/README.md b/java-dates/README.md index 21e54082f4..8171e5def9 100644 --- a/java-dates/README.md +++ b/java-dates/README.md @@ -26,3 +26,6 @@ - [Format ZonedDateTime to String](https://www.baeldung.com/java-format-zoned-datetime-string) - [Convert Between java.time.Instant and java.sql.Timestamp](https://www.baeldung.com/java-time-instant-to-java-sql-timestamp) - [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp) +- [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format) +- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset) +- [Differences Between ZonedDateTime and OffsetDateTime](https://www.baeldung.com/java-zoneddatetime-offsetdatetime) diff --git a/java-dates/pom.xml b/java-dates/pom.xml index 2618fad1d4..d4f690d894 100644 --- a/java-dates/pom.xml +++ b/java-dates/pom.xml @@ -4,8 +4,8 @@ com.baeldung java-dates 0.1.0-SNAPSHOT - jar java-dates + jar com.baeldung @@ -76,7 +76,6 @@ 3.5 - 1.16.12 2.10 3.6.1 diff --git a/java-dates/src/main/java/com/baeldung/datetime/README.md b/java-dates/src/main/java/com/baeldung/datetime/README.md index 1e4adbb612..7d843af9ea 100644 --- a/java-dates/src/main/java/com/baeldung/datetime/README.md +++ b/java-dates/src/main/java/com/baeldung/datetime/README.md @@ -1,2 +1 @@ ### Relevant Articles: -- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro) diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java rename to java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java rename to java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java rename to java-dates/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java diff --git a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java index 1234a700de..a35699e469 100644 --- a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java +++ b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java @@ -8,6 +8,8 @@ import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.Locale; diff --git a/core-java/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java b/java-dates/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java rename to java-dates/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java rename to java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java rename to java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java rename to java-dates/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java diff --git a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml index cf92fe2ecd..582e82d8bb 100644 --- a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml +++ b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml @@ -53,7 +53,7 @@ com.h2database h2 - ${h2-version} + ${h2.version} jar ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global @@ -64,8 +64,4 @@ - - - 1.4.197 - diff --git a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml index f9d63f8623..51ee64097a 100644 --- a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml +++ b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml @@ -53,7 +53,7 @@ com.h2database h2 - ${h2-version} + ${h2.version} jar ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global @@ -64,8 +64,4 @@ - - - 1.4.197 - diff --git a/java-ee-8-security-api/pom.xml b/java-ee-8-security-api/pom.xml index ad33c74ad3..9b8356714f 100644 --- a/java-ee-8-security-api/pom.xml +++ b/java-ee-8-security-api/pom.xml @@ -58,18 +58,6 @@ - - 9080 - 9443 - - 8.0 - 2.3 - 18.0.0.1 - 1.4.197 - - 3.2.2 - - app-auth-basic-store-db app-auth-form-store-ldap @@ -77,4 +65,15 @@ app-auth-custom-no-store + + 9080 + 9443 + + 8.0 + 2.3 + 18.0.0.1 + + 3.2.2 + + diff --git a/java-lite/pom.xml b/java-lite/pom.xml index 03f4e29f4e..ce6e838d92 100644 --- a/java-lite/pom.xml +++ b/java-lite/pom.xml @@ -95,7 +95,6 @@ 1.15 5.1.45 1.7.0 - 1.8.2 1.15 diff --git a/java-math/.gitignore b/java-math/.gitignore new file mode 100644 index 0000000000..30b2b7442c --- /dev/null +++ b/java-math/.gitignore @@ -0,0 +1,4 @@ +/target/ +.settings/ +.classpath +.project \ No newline at end of file diff --git a/java-math/README.md b/java-math/README.md new file mode 100644 index 0000000000..d821348204 --- /dev/null +++ b/java-math/README.md @@ -0,0 +1,10 @@ +## Relevant articles: + +- [Calculate Factorial in Java](https://www.baeldung.com/java-calculate-factorial) +- [Generate Combinations in Java](https://www.baeldung.com/java-combinations-algorithm) +- [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap) +- [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points) +- [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines) +- [Round Up to the Nearest Hundred](https://www.baeldung.com/java-round-up-nearest-hundred) +- [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage) +- [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude) \ No newline at end of file diff --git a/java-math/pom.xml b/java-math/pom.xml new file mode 100644 index 0000000000..f71577b707 --- /dev/null +++ b/java-math/pom.xml @@ -0,0 +1,69 @@ + + 4.0.0 + java-math + 0.0.1-SNAPSHOT + java-math + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.apache.commons + commons-math3 + ${commons-math3.version} + + + com.google.guava + guava + ${guava.version} + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.assertj + assertj-core + ${org.assertj.core.version} + test + + + com.github.dpaukov + combinatoricslib3 + ${combinatoricslib3.version} + + + + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + + + + + 3.6.1 + 3.9.0 + 1.11 + 27.0.1-jre + 3.3.0 + + + \ No newline at end of file diff --git a/java-math/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java new file mode 100644 index 0000000000..40142ce940 --- /dev/null +++ b/java-math/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.combination; + +import java.util.Arrays; +import java.util.Iterator; + +import org.apache.commons.math3.util.CombinatoricsUtils; + +public class ApacheCommonsCombinationGenerator { + + 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/java-math/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java new file mode 100644 index 0000000000..0afdeefb8b --- /dev/null +++ b/java-math/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/java-math/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java new file mode 100644 index 0000000000..d2783881ba --- /dev/null +++ b/java-math/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/java-math/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java new file mode 100644 index 0000000000..676d2f41e3 --- /dev/null +++ b/java-math/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java @@ -0,0 +1,52 @@ +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; + + /** + * 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; + } + + 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--; + } + 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/java-math/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..52305b8c2f --- /dev/null +++ b/java-math/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java @@ -0,0 +1,53 @@ +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; + + /** + * 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(); + 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); + 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/java-math/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..a73447b31d --- /dev/null +++ b/java-math/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java @@ -0,0 +1,50 @@ +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 = 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); + return combinations; + } + + /** + * @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); + helper(combinations, data, start + 1, end, index); + } + } + + public static void main(String[] args) { + SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); + List combinations = generator.generate(N, R); + 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-2/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java b/java-math/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java rename to java-math/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/factorial/Factorial.java b/java-math/src/main/java/com/baeldung/algorithms/factorial/Factorial.java similarity index 100% rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/factorial/Factorial.java rename to java-math/src/main/java/com/baeldung/algorithms/factorial/Factorial.java diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java b/java-math/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java similarity index 100% rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java rename to java-math/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java rename to java-math/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/Mercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/Mercator.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/Mercator.java rename to java-math/src/main/java/com/baeldung/algorithms/mercator/Mercator.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java rename to java-math/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java diff --git a/java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java b/java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java similarity index 93% rename from java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java rename to java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java index e74de2cc67..f69b23146e 100644 --- a/java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java +++ b/java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java @@ -1,4 +1,4 @@ -package com.baeldung.percentage; +package com.baeldung.algorithms.percentage; import java.util.Scanner; diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java b/java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java rename to java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java b/java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java rename to java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java b/java-math/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java similarity index 100% rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java rename to java-math/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java diff --git a/java-math/src/main/resources/logback.xml b/java-math/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/java-math/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/java-math/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java new file mode 100644 index 0000000000..987b6ddae6 --- /dev/null +++ b/java-math/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()); + } +} diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java similarity index 93% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java index 785afdbb2b..784681a807 100644 --- a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java +++ b/java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java @@ -2,8 +2,6 @@ package com.baeldung.algorithms.distancebetweenpoints; import org.junit.Test; -import com.baeldung.algorithms.distancebetweenpoints.DistanceBetweenPointsService; - import static org.junit.Assert.assertEquals; public class DistanceBetweenPointsServiceUnitTest { diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java similarity index 100% rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java similarity index 100% rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java similarity index 100% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java similarity index 100% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java diff --git a/java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java similarity index 95% rename from java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java index 202d4f8112..e49acc0c4b 100644 --- a/java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java +++ b/java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.percentage; +package com.baeldung.algorithms.percentage; import org.junit.Assert; import org.junit.Test; diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java similarity index 93% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java index 6707b34477..e4bb614b48 100644 --- a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java +++ b/java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java @@ -4,9 +4,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; import org.junit.Test; -import com.baeldung.algorithms.rectanglesoverlap.Point; -import com.baeldung.algorithms.rectanglesoverlap.Rectangle; - public class RectangleUnitTest { @Test diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java similarity index 100% rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java rename to java-math/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java diff --git a/java-numbers/README.md b/java-numbers/README.md index 1138d9a74c..2b1131f325 100644 --- a/java-numbers/README.md +++ b/java-numbers/README.md @@ -13,3 +13,9 @@ - [Find All Pairs of Numbers in an Array That Add Up to a Given Sum](http://www.baeldung.com/java-algorithm-number-pairs-sum) - [Java – Random Long, Float, Integer and Double](http://www.baeldung.com/java-generate-random-long-float-integer-double) - [Using Math.sin with Degrees](https://www.baeldung.com/java-math-sin-degrees) +- [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat) +- [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root) +- [Convert Double to String, Removing Decimal Places](https://www.baeldung.com/java-double-to-string) +- [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order) +- [Calculate the Area of a Circle in Java](https://www.baeldung.com/java-calculate-circle-area) +- [A Guide to the Java Math Class](https://www.baeldung.com/java-lang-math) \ No newline at end of file diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml index bb63c8cfe1..daed356f66 100644 --- a/java-numbers/pom.xml +++ b/java-numbers/pom.xml @@ -4,8 +4,8 @@ 4.0.0 java-numbers 0.1.0-SNAPSHOT - jar java-numbers + jar com.baeldung @@ -13,6 +13,7 @@ 0.0.1-SNAPSHOT ../parent-java + log4j @@ -37,7 +38,7 @@ org.openjdk.jmh jmh-generator-annprocess - ${jmh-generator-annprocess.version} + ${jmh-generator.version} org.apache.commons @@ -72,16 +73,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*IntegrationTest.java - - true - - org.apache.maven.plugins @@ -136,8 +127,6 @@ 1.7.21 1.1.7 - 1.19 - 1.19 2.21.0 3.0.0-M1 diff --git a/core-java/src/main/java/com/baeldung/area/circle/Circle.java b/java-numbers/src/main/java/com/baeldung/area/circle/Circle.java similarity index 100% rename from core-java/src/main/java/com/baeldung/area/circle/Circle.java rename to java-numbers/src/main/java/com/baeldung/area/circle/Circle.java diff --git a/core-java/src/main/java/com/baeldung/area/circle/CircleArea.java b/java-numbers/src/main/java/com/baeldung/area/circle/CircleArea.java similarity index 100% rename from core-java/src/main/java/com/baeldung/area/circle/CircleArea.java rename to java-numbers/src/main/java/com/baeldung/area/circle/CircleArea.java diff --git a/core-java/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java b/java-numbers/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java similarity index 100% rename from core-java/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java rename to java-numbers/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java diff --git a/core-java/src/main/java/com/baeldung/nth/root/main/Main.java b/java-numbers/src/main/java/com/baeldung/nth/root/main/Main.java similarity index 100% rename from core-java/src/main/java/com/baeldung/nth/root/main/Main.java rename to java-numbers/src/main/java/com/baeldung/nth/root/main/Main.java diff --git a/java-numbers/src/main/java/com/baeldung/random/SecureRandomDemo.java b/java-numbers/src/main/java/com/baeldung/random/SecureRandomDemo.java new file mode 100644 index 0000000000..02f815f5a7 --- /dev/null +++ b/java-numbers/src/main/java/com/baeldung/random/SecureRandomDemo.java @@ -0,0 +1,36 @@ +package com.baeldung.random; + +import java.security.SecureRandom; +import java.security.NoSuchAlgorithmException; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.DoubleStream; + +public interface SecureRandomDemo { + + public static void generateSecureRandomValues() { + SecureRandom sr = new SecureRandom(); + + int randomInt = sr.nextInt(); + long randomLong = sr.nextLong(); + float randomFloat = sr.nextFloat(); + double randomDouble = sr.nextDouble(); + boolean randomBoolean = sr.nextBoolean(); + + IntStream randomIntStream = sr.ints(); + LongStream randomLongStream = sr.longs(); + DoubleStream randomDoubleStream = sr.doubles(); + + byte[] values = new byte[124]; + sr.nextBytes(values); + } + + public static SecureRandom getSecureRandomForAlgorithm(String algorithm) throws NoSuchAlgorithmException { + if (algorithm == null || algorithm.isEmpty()) { + return new SecureRandom(); + } + + return SecureRandom.getInstance(algorithm); + } + +} diff --git a/core-java/src/main/java/com/baeldung/string/DoubleToString.java b/java-numbers/src/main/java/com/baeldung/string/DoubleToString.java similarity index 99% rename from core-java/src/main/java/com/baeldung/string/DoubleToString.java rename to java-numbers/src/main/java/com/baeldung/string/DoubleToString.java index d26d26f3df..dd55ba51ad 100644 --- a/core-java/src/main/java/com/baeldung/string/DoubleToString.java +++ b/java-numbers/src/main/java/com/baeldung/string/DoubleToString.java @@ -38,4 +38,5 @@ public class DoubleToString { return df.format(d); } + } diff --git a/core-java/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java b/java-numbers/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java rename to java-numbers/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/java/math/MathUnitTest.java b/java-numbers/src/test/java/com/baeldung/java/math/MathUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/math/MathUnitTest.java rename to java-numbers/src/test/java/com/baeldung/java/math/MathUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java b/java-numbers/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java rename to java-numbers/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java b/java-numbers/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java rename to java-numbers/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java b/java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java rename to java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java b/java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java rename to java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java b/java-numbers/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java rename to java-numbers/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java diff --git a/java-streams-2/README.md b/java-streams-2/README.md new file mode 100644 index 0000000000..851d3d71e2 --- /dev/null +++ b/java-streams-2/README.md @@ -0,0 +1,4 @@ +### Relevant Articles: +- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce) +- [How to Break from Java Stream forEach](https://www.baeldung.com/java-break-stream-foreach) +- [Java IntStream Conversions](https://www.baeldung.com/java-intstream-convert) diff --git a/java-streams-2/pom.xml b/java-streams-2/pom.xml new file mode 100644 index 0000000000..f7a0379ac5 --- /dev/null +++ b/java-streams-2/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + com.baeldung.javastreams2 + javastreams2 + 1.0 + javastreams2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator.version} + + + junit + junit + ${junit.version} + test + jar + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + UTF-8 + 1.9 + 1.9 + 3.11.1 + + \ No newline at end of file diff --git a/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomForEach.java b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomForEach.java new file mode 100644 index 0000000000..1f8866b16c --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomForEach.java @@ -0,0 +1,32 @@ +package com.baeldung.breakforeach; + +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + +public class CustomForEach { + + public static class Breaker { + private boolean shouldBreak = false; + + public void stop() { + shouldBreak = true; + } + + boolean get() { + return shouldBreak; + } + } + + public static void forEach(Stream stream, BiConsumer consumer) { + Spliterator spliterator = stream.spliterator(); + boolean hadNext = true; + Breaker breaker = new Breaker(); + + while (hadNext && !breaker.get()) { + hadNext = spliterator.tryAdvance(elem -> { + consumer.accept(elem, breaker); + }); + } + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomSpliterator.java b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomSpliterator.java new file mode 100644 index 0000000000..cfe4bedac3 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomSpliterator.java @@ -0,0 +1,31 @@ +package com.baeldung.breakforeach; + +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class CustomSpliterator extends Spliterators.AbstractSpliterator { + + private Spliterator splitr; + private Predicate predicate; + private boolean isMatched = true; + + public CustomSpliterator(Spliterator splitr, Predicate predicate) { + super(splitr.estimateSize(), 0); + this.splitr = splitr; + this.predicate = predicate; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + boolean hadNext = splitr.tryAdvance(elem -> { + if (predicate.test(elem) && isMatched) { + consumer.accept(elem); + } else { + isMatched = false; + } + }); + return hadNext && isMatched; + } +} \ No newline at end of file diff --git a/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomTakeWhile.java b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomTakeWhile.java new file mode 100644 index 0000000000..05574f9ae6 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/breakforeach/CustomTakeWhile.java @@ -0,0 +1,14 @@ +package com.baeldung.breakforeach; + +import java.util.function.Predicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class CustomTakeWhile { + + public static Stream takeWhile(Stream stream, Predicate predicate) { + CustomSpliterator customSpliterator = new CustomSpliterator<>(stream.spliterator(), predicate); + return StreamSupport.stream(customSpliterator, false); + } + +} diff --git a/java-streams-2/src/main/java/com/baeldung/breakforeach/TakeWhileExample.java b/java-streams-2/src/main/java/com/baeldung/breakforeach/TakeWhileExample.java new file mode 100644 index 0000000000..1838ae5fb7 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/breakforeach/TakeWhileExample.java @@ -0,0 +1,26 @@ +package com.baeldung.breakforeach; + +import java.util.List; +import java.util.stream.Stream; + +import static java.util.Arrays.asList; + +public class TakeWhileExample { + + public static void takeWhileJava9() { + Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck") + .takeWhile(n -> n.length() % 2 != 0) + .forEach(System.out::println); // cat, dog + } + + public static void plainForLoopWithBreak() { + List list = asList("cat", "dog", "elephant", "fox", "rabbit", "duck"); + for (int i = 0; i < list.size(); i++) { + String item = list.get(i); + if (item.length() % 2 == 0) { + break; + } + System.out.println(item); + } + } +} \ 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/breakforeach/BreakFromStreamForEachUnitTest.java b/java-streams-2/src/test/java/com/baeldung/breakforeach/BreakFromStreamForEachUnitTest.java new file mode 100644 index 0000000000..23653c0a39 --- /dev/null +++ b/java-streams-2/src/test/java/com/baeldung/breakforeach/BreakFromStreamForEachUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.breakforeach; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +public class BreakFromStreamForEachUnitTest { + + @Test + public void whenCustomTakeWhileIsCalled_ThenCorrectItemsAreReturned() { + Stream initialStream = Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck"); + + List result = CustomTakeWhile.takeWhile(initialStream, x -> x.length() % 2 != 0) + .collect(Collectors.toList()); + + assertEquals(asList("cat", "dog"), result); + } + + @Test + public void whenCustomForEachIsCalled_ThenCorrectItemsAreReturned() { + Stream initialStream = Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck"); + List result = new ArrayList<>(); + + CustomForEach.forEach(initialStream, (elem, breaker) -> { + if (elem.length() % 2 == 0) { + breaker.stop(); + } else { + result.add(elem); + } + }); + + assertEquals(asList("cat", "dog"), result); + } + +} diff --git a/java-streams-2/src/test/java/com/baeldung/convert/intstreams/IntStreamsConversionsUnitTest.java b/java-streams-2/src/test/java/com/baeldung/convert/intstreams/IntStreamsConversionsUnitTest.java new file mode 100644 index 0000000000..3f2fd1641e --- /dev/null +++ b/java-streams-2/src/test/java/com/baeldung/convert/intstreams/IntStreamsConversionsUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.convert.intstreams; + +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static org.assertj.core.api.Assertions.assertThat; + +public class IntStreamsConversionsUnitTest { + + @Test + public void intStreamToArray() { + int[] first50EvenNumbers = IntStream.iterate(0, i -> i + 2) + .limit(50) + .toArray(); + + assertThat(first50EvenNumbers).hasSize(50); + assertThat(first50EvenNumbers[2]).isEqualTo(4); + } + + @Test + public void intStreamToList() { + List first50IntegerNumbers = IntStream.range(0, 50) + .boxed() + .collect(Collectors.toList()); + + assertThat(first50IntegerNumbers).hasSize(50); + assertThat(first50IntegerNumbers.get(2)).isEqualTo(2); + } + + @Test + public void intStreamToString() { + String first3numbers = IntStream.of(0, 1, 2) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ", "[", "]")); + + assertThat(first3numbers).isEqualTo("[0, 1, 2]"); + } +} 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); + } +} diff --git a/java-streams/README.md b/java-streams/README.md index 2550f08650..0c9588c47e 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -3,14 +3,18 @@ ## 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) - [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element) -- [”Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception) +- [“Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception) - [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream) - [How to Iterate Over a Stream With Indices](http://www.baeldung.com/java-stream-indices) - [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams) - [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering) - [Introduction to Protonpack](https://www.baeldung.com/java-protonpack) +- [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) diff --git a/java-streams/pom.xml b/java-streams/pom.xml index 2b52ebb4b3..b0c56ecdf9 100644 --- a/java-streams/pom.xml +++ b/java-streams/pom.xml @@ -3,8 +3,8 @@ 4.0.0 java-streams 0.1.0-SNAPSHOT - jar java-streams + jar com.baeldung @@ -18,12 +18,12 @@ org.openjdk.jmh jmh-core - ${jmh.version} + ${jmh-core.version} org.openjdk.jmh jmh-generator-annprocess - ${jmh.version} + ${jmh-generator.version} provided @@ -94,10 +94,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + ${maven-compiler-plugin.version} - 1.8 - 1.8 + ${maven.compiler.source} + ${maven.compiler.target} -parameters @@ -106,9 +106,7 @@ - 1.21 3.5 - 1.16.12 0.9.0 1.15 0.6.5 @@ -117,5 +115,8 @@ 3.11.1 1.8.9 + 3.1 + 1.8 + 1.8 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/main/java/com/baeldung/stream/filter/Customer.java b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java index 49da6e7175..fd4f6021ff 100644 --- a/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java +++ b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java @@ -32,7 +32,7 @@ public class Customer { return this.points > points; } - public boolean hasOverThousandPoints() { + public boolean hasOverHundredPoints() { return this.points > 100; } diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java new file mode 100644 index 0000000000..3170b1fb31 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java @@ -0,0 +1,8 @@ +package com.baeldung.stream.sum; + +public class ArithmeticUtils { + + public static int add(int a, int b) { + return a + b; + } +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/Item.java b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java new file mode 100644 index 0000000000..2f162d6eda --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java @@ -0,0 +1,31 @@ +package com.baeldung.stream.sum; + +public class Item { + + private int id; + private Integer price; + + public Item(int id, Integer price) { + super(); + this.id = id; + this.price = price; + } + + // Standard getters and setters + public long getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } + +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java new file mode 100644 index 0000000000..2f63cf8629 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java @@ -0,0 +1,59 @@ +package com.baeldung.stream.sum; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class StreamSumCalculator { + + public static Integer getSumUsingCustomizedAccumulator(List integers) { + return integers.stream() + .reduce(0, ArithmeticUtils::add); + + } + + public static Integer getSumUsingJavaAccumulator(List integers) { + return integers.stream() + .reduce(0, Integer::sum); + + } + + public static Integer getSumUsingReduce(List integers) { + return integers.stream() + .reduce(0, (a, b) -> a + b); + + } + + public static Integer getSumUsingCollect(List integers) { + + return integers.stream() + .collect(Collectors.summingInt(Integer::intValue)); + + } + + public static Integer getSumUsingSum(List integers) { + + return integers.stream() + .mapToInt(Integer::intValue) + .sum(); + } + + public static Integer getSumOfMapValues(Map map) { + + return map.values() + .stream() + .mapToInt(Integer::valueOf) + .sum(); + } + + public static Integer getSumIntegersFromString(String str) { + + Integer sum = Arrays.stream(str.split(" ")) + .filter((s) -> s.matches("\\d+")) + .mapToInt(Integer::valueOf) + .sum(); + + return sum; + } +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java new file mode 100644 index 0000000000..b83616928e --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java @@ -0,0 +1,38 @@ +package com.baeldung.stream.sum; + +import java.util.List; +import java.util.stream.Collectors; + +public class StreamSumCalculatorWithObject { + + public static Integer getSumUsingCustomizedAccumulator(List items) { + return items.stream() + .map(x -> x.getPrice()) + .reduce(0, ArithmeticUtils::add); + } + + public static Integer getSumUsingJavaAccumulator(List items) { + return items.stream() + .map(x -> x.getPrice()) + .reduce(0, Integer::sum); + } + + public static Integer getSumUsingReduce(List items) { + return items.stream() + .map(item -> item.getPrice()) + .reduce(0, (a, b) -> a + b); + } + + public static Integer getSumUsingCollect(List items) { + return items.stream() + .map(x -> x.getPrice()) + .collect(Collectors.summingInt(Integer::intValue)); + } + + public static Integer getSumUsingSum(List items) { + return items.stream() + .mapToInt(x -> x.getPrice()) + .sum(); + } + +} 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); + } +} diff --git a/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java new file mode 100644 index 0000000000..a3a2816e9c --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.stream; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.StringWriter; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class PeekUnitTest { + + private StringWriter out; + + @BeforeEach + void setup() { + out = new StringWriter(); + } + + @Test + void givenStringStream_whenCallingPeekOnly_thenNoElementProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append); + + // then + assertThat(out.toString()).isEmpty(); + } + + @Test + void givenStringStream_whenCallingForEachOnly_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndNoopForEach_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .forEach(this::noop); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndCollect_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .collect(Collectors.toList()); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndForEach_thenElementsProcessedTwice() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("AliceAliceBobBobChuckChuck"); + } + + @Test + void givenStringStream_whenCallingPeek_thenElementsProcessedTwice() { + // given + Stream userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck")); + + // when + userStream.peek(u -> u.setName(u.getName().toLowerCase())) + .map(User::getName) + .forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("alicebobchuck"); + } + + private static class User { + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + private void noop(String s) { + } + +} diff --git a/java-streams/src/test/java/com/baeldung/stream/StreamMapUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/StreamMapUnitTest.java new file mode 100644 index 0000000000..5cb2a274d1 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/StreamMapUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.stream; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class StreamMapUnitTest { + + private Map books; + + @Before + public void setup() { + books = new HashMap<>(); + books.put("978-0201633610", "Design patterns : elements of reusable object-oriented software"); + books.put("978-1617291999", "Java 8 in Action: Lambdas, Streams, and functional-style programming"); + books.put("978-0134685991", "Effective Java"); + } + + + @Test + public void whenOptionalVersionCalledForExistingTitle_thenReturnOptionalWithISBN() { + Optional optionalIsbn = books.entrySet().stream() + .filter(e -> "Effective Java".equals(e.getValue())) + .map(Map.Entry::getKey).findFirst(); + + assertEquals("978-0134685991", optionalIsbn.get()); + } + + @Test + public void whenOptionalVersionCalledForNonExistingTitle_thenReturnEmptyOptionalForISBN() { + Optional optionalIsbn = books.entrySet().stream() + .filter(e -> "Non Existent Title".equals(e.getValue())) + .map(Map.Entry::getKey).findFirst(); + + assertEquals(false, optionalIsbn.isPresent()); + } + + @Test + public void whenMultipleResultsVersionCalledForExistingTitle_aCollectionWithMultipleValuesIsReturned() { + books.put("978-0321356680", "Effective Java: Second Edition"); + + List isbnCodes = books.entrySet().stream() + .filter(e -> e.getValue().startsWith("Effective Java")) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + assertTrue(isbnCodes.contains("978-0321356680")); + assertTrue(isbnCodes.contains("978-0134685991")); + } + + @Test + public void whenMultipleResultsVersionCalledForNonExistingTitle_aCollectionWithNoValuesIsReturned() { + List isbnCodes = books.entrySet().stream() + .filter(e -> e.getValue().startsWith("Spring")) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + assertTrue(isbnCodes.isEmpty()); + } + + @Test + public void whenKeysFollowingPatternReturnsAllValuesForThoseKeys() { + List titlesForKeyPattern = books.entrySet().stream() + .filter(e -> e.getKey().startsWith("978-0")) + .map(Map.Entry::getValue) + .collect(Collectors.toList()); + assertEquals(2, titlesForKeyPattern.size()); + assertTrue(titlesForKeyPattern.contains("Design patterns : elements of reusable object-oriented software")); + assertTrue(titlesForKeyPattern.contains("Effective Java")); + } + +} diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java new file mode 100644 index 0000000000..742e5aedc9 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.stream.filter; + +import org.junit.Test; +import org.junit.Before; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StreamCountUnitTest { + + private List customers; + + @Before + public void setUp() { + Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e"); + Customer sarah = new Customer("Sarah M.", 200); + Customer charles = new Customer("Charles B.", 150); + Customer mary = new Customer("Mary T.", 1, "https://images.unsplash.com/photo-1543297057-25167dfc180e"); + customers = Arrays.asList(john, sarah, charles, mary); + } + + @Test + public void givenListOfCustomers_whenCount_thenGetListSize() { + long count = customers + .stream() + .count(); + + assertThat(count).isEqualTo(4L); + } + + @Test + public void givenListOfCustomers_whenFilterByPointsOver100AndCount_thenGetTwo() { + long countBigCustomers = customers + .stream() + .filter(c -> c.getPoints() > 100) + .count(); + + assertThat(countBigCustomers).isEqualTo(2L); + } + + @Test + public void givenListOfCustomers_whenFilterByPointsAndNameAndCount_thenGetOne() { + long count = customers + .stream() + .filter(c -> c.getPoints() > 10 && c.getName().startsWith("Charles")) + .count(); + + assertThat(count).isEqualTo(1L); + } + + @Test + public void givenListOfCustomers_whenNoneMatchesFilterAndCount_thenGetZero() { + long count = customers + .stream() + .filter(c -> c.getPoints() > 500) + .count(); + + assertThat(count).isEqualTo(0L); + } + + @Test + public void givenListOfCustomers_whenUsingMethodOverHundredPointsAndCount_thenGetTwo() { + long count = customers + .stream() + .filter(Customer::hasOverHundredPoints) + .count(); + + assertThat(count).isEqualTo(2L); + } +} diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java index cf82802940..5ad875f61e 100644 --- a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java @@ -62,7 +62,7 @@ public class StreamFilterUnitTest { List customersWithMoreThan100Points = customers .stream() - .filter(Customer::hasOverThousandPoints) + .filter(Customer::hasOverHundredPoints) .collect(Collectors.toList()); assertThat(customersWithMoreThan100Points).hasSize(2); @@ -81,7 +81,7 @@ public class StreamFilterUnitTest { .flatMap(c -> c .map(Stream::of) .orElseGet(Stream::empty)) - .filter(Customer::hasOverThousandPoints) + .filter(Customer::hasOverHundredPoints) .collect(Collectors.toList()); assertThat(customersWithMoreThan100Points).hasSize(2); @@ -156,4 +156,5 @@ public class StreamFilterUnitTest { }) .collect(Collectors.toList())).isInstanceOf(RuntimeException.class); } + } diff --git a/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java new file mode 100644 index 0000000000..46e1af9a4a --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java @@ -0,0 +1,136 @@ +package com.baeldung.stream.sum; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +public class StreamSumUnitTest { + + @Test + public void givenListOfIntegersWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingCustomizedAccumulator(integers); + assertEquals(15, sum.intValue()); + + } + + @Test + public void givenListOfIntegersWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingJavaAccumulator(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingReduceThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingReduce(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingCollectThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingCollect(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingSumThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingSum(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingCustomizedAccumulator(items); + assertEquals(90, sum.intValue()); + + } + + @Test + public void givenListOfItemsWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingJavaAccumulator(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingReduceThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingReduce(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingCollectThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingCollect(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingSumThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingSum(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenMapWhenSummingThenCorrectValueReturned() { + Map map = new HashMap(); + map.put(1, 10); + map.put(2, 15); + map.put(3, 25); + map.put(4, 40); + + Integer sum = StreamSumCalculator.getSumOfMapValues(map); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenStringWhenSummingThenCorrectValueReturned() { + String string = "Item1 10 Item2 25 Item3 30 Item4 45"; + + Integer sum = StreamSumCalculator.getSumIntegersFromString(string); + assertEquals(110, sum.intValue()); + } + +} diff --git a/java-strings-2/README.MD b/java-strings-2/README.MD new file mode 100644 index 0000000000..6548c48f2c --- /dev/null +++ b/java-strings-2/README.MD @@ -0,0 +1,6 @@ +## Relevant Articles + +- [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting) +- [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring) +- [Removing Stopwords from a String in Java](https://www.baeldung.com/java-string-remove-stopwords) +- [Blank and Empty Strings in Java](https://www.baeldung.com/java-blank-empty-strings) diff --git a/java-strings-2/pom.xml b/java-strings-2/pom.xml new file mode 100755 index 0000000000..7342953d15 --- /dev/null +++ b/java-strings-2/pom.xml @@ -0,0 +1,113 @@ + + 4.0.0 + java-strings-2 + 0.1.0-SNAPSHOT + jar + java-strings-2 + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + + + com.ibm.icu + icu4j + ${icu4j.version} + + + com.google.guava + guava + ${guava.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + junit + junit + ${junit.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + org.apache.commons + commons-text + ${commons-text.version} + + + javax.validation + validation-api + 2.0.0.Final + + + org.hibernate.validator + hibernate-validator + 6.0.2.Final + + + javax.el + javax.el-api + 3.0.0 + + + org.glassfish.web + javax.el + 2.2.6 + + + + + + java-strings-2 + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + -parameters + + + + + + + 3.8.1 + 61.1 + 28.0-jre + 1.4 + + + \ No newline at end of file diff --git a/java-strings-2/src/main/java/com/baeldung/localization/App.java b/java-strings-2/src/main/java/com/baeldung/localization/App.java new file mode 100644 index 0000000000..c2b687933d --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/App.java @@ -0,0 +1,21 @@ +package com.baeldung.localization; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public class App { + + /** + * Runs all available formatter + * @throws ParseException + */ + public static void main(String[] args) { + List locales = Arrays.asList(new Locale[] { Locale.UK, Locale.ITALY, Locale.FRANCE, Locale.forLanguageTag("pl-PL") }); + Localization.run(locales); + JavaSEFormat.run(locales); + ICUFormat.run(locales); + } + +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java b/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java new file mode 100644 index 0000000000..f7bc357933 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java @@ -0,0 +1,29 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import com.ibm.icu.text.MessageFormat; + +public class ICUFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + String format = bundle.getString("label-icu"); + MessageFormat formatter = new MessageFormat(format, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("ICU formatter"); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 3 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 3 }))); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java b/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java new file mode 100644 index 0000000000..c95dfffa13 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java @@ -0,0 +1,24 @@ +package com.baeldung.localization; + +import java.text.MessageFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class JavaSEFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + final String pattern = bundle.getString("label"); + final MessageFormat formatter = new MessageFormat(pattern, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("Java formatter"); + final Date date = new Date(System.currentTimeMillis()); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 2 }))); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/Localization.java b/java-strings-2/src/main/java/com/baeldung/localization/Localization.java new file mode 100644 index 0000000000..17a6598ce0 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/Localization.java @@ -0,0 +1,18 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class Localization { + + public static String getLabel(Locale locale) { + final ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); + return bundle.getString("label"); + } + + public static void run(List locales) { + locales.forEach(locale -> System.out.println(getLabel(locale))); + } + +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/emptystrings/EmptyStringCheck.java b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/EmptyStringCheck.java new file mode 100644 index 0000000000..6d3234a4ec --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/EmptyStringCheck.java @@ -0,0 +1,8 @@ +package com.baeldung.string.emptystrings; + +class EmptyStringCheck { + + boolean isEmptyString(String string) { + return string == null || string.isEmpty(); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/emptystrings/Java5EmptyStringCheck.java b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/Java5EmptyStringCheck.java new file mode 100644 index 0000000000..096b83acea --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/Java5EmptyStringCheck.java @@ -0,0 +1,8 @@ +package com.baeldung.string.emptystrings; + +class Java5EmptyStringCheck { + + boolean isEmptyString(String string) { + return string == null || string.length() == 0; + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/emptystrings/PlainJavaBlankStringCheck.java b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/PlainJavaBlankStringCheck.java new file mode 100644 index 0000000000..26e281c9b7 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/PlainJavaBlankStringCheck.java @@ -0,0 +1,8 @@ +package com.baeldung.string.emptystrings; + +class PlainJavaBlankStringCheck { + + boolean isBlankString(String string) { + return string == null || string.trim().isEmpty(); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/emptystrings/SomeClassWithValidations.java b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/SomeClassWithValidations.java new file mode 100644 index 0000000000..8c484efb43 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/emptystrings/SomeClassWithValidations.java @@ -0,0 +1,14 @@ +package com.baeldung.string.emptystrings; + +import javax.validation.constraints.Pattern; + +class SomeClassWithValidations { + + @Pattern(regexp = "\\A(?!\\s*\\Z).+") + private String someString; + + SomeClassWithValidations setSomeString(String someString) { + this.someString = someString; + return this; + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java b/java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java new file mode 100644 index 0000000000..1bde2dcb63 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/multiline/MultiLineString.java @@ -0,0 +1,67 @@ +package com.baeldung.string.multiline; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Paths; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; + +public class MultiLineString { + + String newLine = System.getProperty("line.separator"); + + public String stringConcatenation() { + return "Get busy living" + .concat(newLine) + .concat("or") + .concat(newLine) + .concat("get busy dying.") + .concat(newLine) + .concat("--Stephen King"); + } + + public String stringJoin() { + return String.join(newLine, + "Get busy living", + "or", + "get busy dying.", + "--Stephen King"); + } + + public String stringBuilder() { + return new StringBuilder() + .append("Get busy living") + .append(newLine) + .append("or") + .append(newLine) + .append("get busy dying.") + .append(newLine) + .append("--Stephen King") + .toString(); + } + + public String stringWriter() { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + printWriter.println("Get busy living"); + printWriter.println("or"); + printWriter.println("get busy dying."); + printWriter.println("--Stephen King"); + return stringWriter.toString(); + } + + public String guavaJoiner() { + return Joiner.on(newLine).join(ImmutableList.of("Get busy living", + "or", + "get busy dying.", + "--Stephen King")); + } + + public String loadFromFile() throws IOException { + return new String(Files.readAllBytes(Paths.get("src/main/resources/stephenking.txt"))); + } + +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/performance/RemovingStopwordsPerformanceComparison.java b/java-strings-2/src/main/java/com/baeldung/string/performance/RemovingStopwordsPerformanceComparison.java new file mode 100644 index 0000000000..5b455459cd --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/performance/RemovingStopwordsPerformanceComparison.java @@ -0,0 +1,73 @@ +package com.baeldung.string.performance; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +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.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + + +@Fork(value = 3, warmups = 1) +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +public class RemovingStopwordsPerformanceComparison { + + private String data; + + private List stopwords; + + private String stopwordsRegex; + + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Setup + public void setup() throws IOException { + data = new String(Files.readAllBytes(Paths.get("src/main/resources/shakespeare-hamlet.txt"))); + data = data.toLowerCase(); + stopwords = Files.readAllLines(Paths.get("src/main/resources/english_stopwords.txt")); + stopwordsRegex = stopwords.stream().collect(Collectors.joining("|", "\\b(", ")\\b\\s?")); + } + + @Benchmark + public String removeManually() { + String[] allWords = data.split(" "); + StringBuilder builder = new StringBuilder(); + for(String word:allWords) { + if(! stopwords.contains(word)) { + builder.append(word); + builder.append(' '); + } + } + return builder.toString().trim(); + } + + @Benchmark + public String removeAll() { + ArrayList allWords = Stream.of(data.split(" ")) + .collect(Collectors.toCollection(ArrayList::new)); + allWords.removeAll(stopwords); + return allWords.stream().collect(Collectors.joining(" ")); + } + + @Benchmark + public String replaceRegex() { + return data.replaceAll(stopwordsRegex, ""); + } + +} \ No newline at end of file diff --git a/java-strings-2/src/main/java/com/baeldung/string/repetition/SubstringRepetition.java b/java-strings-2/src/main/java/com/baeldung/string/repetition/SubstringRepetition.java new file mode 100644 index 0000000000..466ce9146b --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/repetition/SubstringRepetition.java @@ -0,0 +1,29 @@ +package com.baeldung.string.repetition; + +public class SubstringRepetition { + + public static boolean containsOnlySubstrings(String string) { + + if (string.length() < 2) { + return false; + } + + StringBuilder substr = new StringBuilder(); + for (int i = 0; i < string.length() / 2; i++) { + substr.append(string.charAt(i)); + + String clearedFromSubstrings = string.replaceAll(substr.toString(), ""); + + if (clearedFromSubstrings.length() == 0) { + return true; + } + } + + return false; + } + + public static boolean containsOnlySubstringsEfficient(String string) { + + return ((string + string).indexOf(string, 1) != string.length()); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/reverse/ReverseStringExamples.java b/java-strings-2/src/main/java/com/baeldung/string/reverse/ReverseStringExamples.java new file mode 100644 index 0000000000..1a58d09598 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/reverse/ReverseStringExamples.java @@ -0,0 +1,56 @@ +package com.baeldung.string.reverse; + +import org.apache.commons.lang3.StringUtils; + +public class ReverseStringExamples { + + public static String reverse(String input) { + if (input == null) { + return null; + } + + String output = ""; + + for (int i = input.length() - 1; i >= 0; i--) { + output = output + input.charAt(i); + } + + return output; + } + + public static String reverseUsingStringBuilder(String input) { + if (input == null) { + return null; + } + + StringBuilder output = new StringBuilder(input).reverse(); + + return output.toString(); + } + + public static String reverseUsingApacheCommons(String input) { + return StringUtils.reverse(input); + } + + public static String reverseTheOrderOfWords(String sentence) { + if (sentence == null) { + return null; + } + + StringBuilder output = new StringBuilder(); + String[] words = sentence.split(" "); + + for (int i = words.length - 1; i >= 0; i--) { + output.append(words[i]); + output.append(" "); + } + + return output.toString() + .trim(); + } + + public static String reverseTheOrderOfWordsUsingApacheCommons(String sentence) { + return StringUtils.reverseDelimited(sentence, ' '); + } + +} diff --git a/java-strings-2/src/main/java/com/baeldung/string/search/performance/SubstringSearchPerformanceComparison.java b/java-strings-2/src/main/java/com/baeldung/string/search/performance/SubstringSearchPerformanceComparison.java new file mode 100644 index 0000000000..bf33c47a7e --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/string/search/performance/SubstringSearchPerformanceComparison.java @@ -0,0 +1,58 @@ +package com.baeldung.string.search.performance; + +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +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.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** + * Based on https://github.com/tedyoung/indexof-contains-benchmark + */ +@Fork(5) +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class SubstringSearchPerformanceComparison { + + private String message; + + private Pattern pattern; + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Setup + public void setup() { + message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"; + pattern = Pattern.compile("(? + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/java-strings-2/src/main/resources/messages_en.properties b/java-strings-2/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..bcbca9483c --- /dev/null +++ b/java-strings-2/src/main/resources/messages_en.properties @@ -0,0 +1 @@ +label=Alice has sent you a message. diff --git a/java-strings-2/src/main/resources/messages_fr.properties b/java-strings-2/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..15ad031a30 --- /dev/null +++ b/java-strings-2/src/main/resources/messages_fr.properties @@ -0,0 +1 @@ +label=Alice vous a envoy\u00e9 un message. diff --git a/java-strings-2/src/main/resources/messages_it.properties b/java-strings-2/src/main/resources/messages_it.properties new file mode 100644 index 0000000000..93b99a9483 --- /dev/null +++ b/java-strings-2/src/main/resources/messages_it.properties @@ -0,0 +1 @@ +label=Alice ti ha inviato un messaggio. diff --git a/java-strings-2/src/main/resources/messages_pl.properties b/java-strings-2/src/main/resources/messages_pl.properties new file mode 100644 index 0000000000..a64066deea --- /dev/null +++ b/java-strings-2/src/main/resources/messages_pl.properties @@ -0,0 +1 @@ +label=Alice wys\u0142a\u0142a ci wiadomo\u015B\u0107. diff --git a/java-strings-2/src/main/resources/shakespeare-hamlet.txt b/java-strings-2/src/main/resources/shakespeare-hamlet.txt new file mode 100644 index 0000000000..0156555388 --- /dev/null +++ b/java-strings-2/src/main/resources/shakespeare-hamlet.txt @@ -0,0 +1,4922 @@ +[The Tragedie of Hamlet by William Shakespeare 1599] + + +Actus Primus. Scoena Prima. + +Enter Barnardo and Francisco two Centinels. + + Barnardo. Who's there? + Fran. Nay answer me: Stand & vnfold +your selfe + + Bar. Long liue the King + + Fran. Barnardo? + Bar. He + + Fran. You come most carefully vpon your houre + + Bar. 'Tis now strook twelue, get thee to bed Francisco + + Fran. For this releefe much thankes: 'Tis bitter cold, +And I am sicke at heart + + Barn. Haue you had quiet Guard? + Fran. Not a Mouse stirring + + Barn. Well, goodnight. If you do meet Horatio and +Marcellus, the Riuals of my Watch, bid them make hast. +Enter Horatio and Marcellus. + + Fran. I thinke I heare them. Stand: who's there? + Hor. Friends to this ground + + Mar. And Leige-men to the Dane + + Fran. Giue you good night + + Mar. O farwel honest Soldier, who hath relieu'd you? + Fra. Barnardo ha's my place: giue you goodnight. + +Exit Fran. + + Mar. Holla Barnardo + + Bar. Say, what is Horatio there? + Hor. A peece of him + + Bar. Welcome Horatio, welcome good Marcellus + + Mar. What, ha's this thing appear'd againe to night + + Bar. I haue seene nothing + + Mar. Horatio saies, 'tis but our Fantasie, +And will not let beleefe take hold of him +Touching this dreaded sight, twice seene of vs, +Therefore I haue intreated him along +With vs, to watch the minutes of this Night, +That if againe this Apparition come, +He may approue our eyes, and speake to it + + Hor. Tush, tush, 'twill not appeare + + Bar. Sit downe a-while, +And let vs once againe assaile your eares, +That are so fortified against our Story, +What we two Nights haue seene + + Hor. Well, sit we downe, +And let vs heare Barnardo speake of this + + Barn. Last night of all, +When yond same Starre that's Westward from the Pole +Had made his course t' illume that part of Heauen +Where now it burnes, Marcellus and my selfe, +The Bell then beating one + + Mar. Peace, breake thee of: +Enter the Ghost. + +Looke where it comes againe + + Barn. In the same figure, like the King that's dead + + Mar. Thou art a Scholler; speake to it Horatio + + Barn. Lookes it not like the King? Marke it Horatio + + Hora. Most like: It harrowes me with fear & wonder + Barn. It would be spoke too + + Mar. Question it Horatio + + Hor. What art thou that vsurp'st this time of night, +Together with that Faire and Warlike forme +In which the Maiesty of buried Denmarke +Did sometimes march: By Heauen I charge thee speake + + Mar. It is offended + + Barn. See, it stalkes away + + Hor. Stay: speake; speake: I Charge thee, speake. + +Exit the Ghost. + + Mar. 'Tis gone, and will not answer + + Barn. How now Horatio? You tremble & look pale: +Is not this something more then Fantasie? +What thinke you on't? + Hor. Before my God, I might not this beleeue +Without the sensible and true auouch +Of mine owne eyes + + Mar. Is it not like the King? + Hor. As thou art to thy selfe, +Such was the very Armour he had on, +When th' Ambitious Norwey combatted: +So frown'd he once, when in an angry parle +He smot the sledded Pollax on the Ice. +'Tis strange + + Mar. Thus twice before, and iust at this dead houre, +With Martiall stalke, hath he gone by our Watch + + Hor. In what particular thought to work, I know not: +But in the grosse and scope of my Opinion, +This boades some strange erruption to our State + + Mar. Good now sit downe, & tell me he that knowes +Why this same strict and most obseruant Watch, +So nightly toyles the subiect of the Land, +And why such dayly Cast of Brazon Cannon +And Forraigne Mart for Implements of warre: +Why such impresse of Ship-wrights, whose sore Taske +Do's not diuide the Sunday from the weeke, +What might be toward, that this sweaty hast +Doth make the Night ioynt-Labourer with the day: +Who is't that can informe me? + Hor. That can I, +At least the whisper goes so: Our last King, +Whose Image euen but now appear'd to vs, +Was (as you know) by Fortinbras of Norway, +(Thereto prick'd on by a most emulate Pride) +Dar'd to the Combate. In which, our Valiant Hamlet, +(For so this side of our knowne world esteem'd him) +Did slay this Fortinbras: who by a Seal'd Compact, +Well ratified by Law, and Heraldrie, +Did forfeite (with his life) all those his Lands +Which he stood seiz'd on, to the Conqueror: +Against the which, a Moity competent +Was gaged by our King: which had return'd +To the Inheritance of Fortinbras, +Had he bin Vanquisher, as by the same Cou'nant +And carriage of the Article designe, +His fell to Hamlet. Now sir, young Fortinbras, +Of vnimproued Mettle, hot and full, +Hath in the skirts of Norway, heere and there, +Shark'd vp a List of Landlesse Resolutes, +For Foode and Diet, to some Enterprize +That hath a stomacke in't: which is no other +(And it doth well appeare vnto our State) +But to recouer of vs by strong hand +And termes Compulsatiue, those foresaid Lands +So by his Father lost: and this (I take it) +Is the maine Motiue of our Preparations, +The Sourse of this our Watch, and the cheefe head +Of this post-hast, and Romage in the Land. +Enter Ghost againe. + +But soft, behold: Loe, where it comes againe: +Ile crosse it, though it blast me. Stay Illusion: +If thou hast any sound, or vse of Voyce, +Speake to me. If there be any good thing to be done, +That may to thee do ease, and grace to me; speak to me. +If thou art priuy to thy Countries Fate +(Which happily foreknowing may auoyd) Oh speake. +Or, if thou hast vp-hoorded in thy life +Extorted Treasure in the wombe of Earth, +(For which, they say, you Spirits oft walke in death) +Speake of it. Stay, and speake. Stop it Marcellus + + Mar. Shall I strike at it with my Partizan? + Hor. Do, if it will not stand + + Barn. 'Tis heere + + Hor. 'Tis heere + + Mar. 'Tis gone. + +Exit Ghost. + +We do it wrong, being so Maiesticall +To offer it the shew of Violence, +For it is as the Ayre, invulnerable, +And our vaine blowes, malicious Mockery + + Barn. It was about to speake, when the Cocke crew + + Hor. And then it started, like a guilty thing +Vpon a fearfull Summons. I haue heard, +The Cocke that is the Trumpet to the day, +Doth with his lofty and shrill-sounding Throate +Awake the God of Day: and at his warning, +Whether in Sea, or Fire, in Earth, or Ayre, +Th' extrauagant, and erring Spirit, hyes +To his Confine. And of the truth heerein, +This present Obiect made probation + + Mar. It faded on the crowing of the Cocke. +Some sayes, that euer 'gainst that Season comes +Wherein our Sauiours Birch is celebrated, +The Bird of Dawning singeth all night long: +And then (they say) no Spirit can walke abroad, +The nights are wholsome, then no Planets strike, +No Faiery talkes, nor Witch hath power to Charme: +So hallow'd, and so gracious is the time + + Hor. So haue I heard, and do in part beleeue it. +But looke, the Morne in Russet mantle clad, +Walkes o're the dew of yon high Easterne Hill, +Breake we our Watch vp, and by my aduice +Let vs impart what we haue seene to night +Vnto yong Hamlet. For vpon my life, +This Spirit dumbe to vs, will speake to him: +Do you consent we shall acquaint him with it, +As needfull in our Loues, fitting our Duty? + Mar. Let do't I pray, and I this morning know +Where we shall finde him most conueniently. + +Exeunt. + +Scena Secunda. + +Enter Claudius King of Denmarke, Gertrude the Queene, Hamlet, +Polonius, +Laertes, and his Sister Ophelia, Lords Attendant. + + King. Though yet of Hamlet our deere Brothers death +The memory be greene: and that it vs befitted +To beare our hearts in greefe, and our whole Kingdome +To be contracted in one brow of woe: +Yet so farre hath Discretion fought with Nature, +That we with wisest sorrow thinke on him, +Together with remembrance of our selues. +Therefore our sometimes Sister, now our Queene, +Th' imperiall Ioyntresse of this warlike State, +Haue we, as 'twere, with a defeated ioy, +With one Auspicious, and one Dropping eye, +With mirth in Funerall, and with Dirge in Marriage, +In equall Scale weighing Delight and Dole +Taken to Wife; nor haue we heerein barr'd +Your better Wisedomes, which haue freely gone +With this affaire along, for all our Thankes. +Now followes, that you know young Fortinbras, +Holding a weake supposall of our worth; +Or thinking by our late deere Brothers death, +Our State to be disioynt, and out of Frame, +Colleagued with the dreame of his Aduantage; +He hath not fayl'd to pester vs with Message, +Importing the surrender of those Lands +Lost by his Father: with all Bonds of Law +To our most valiant Brother. So much for him. +Enter Voltemand and Cornelius. + +Now for our selfe, and for this time of meeting +Thus much the businesse is. We haue heere writ +To Norway, Vncle of young Fortinbras, +Who Impotent and Bedrid, scarsely heares +Of this his Nephewes purpose, to suppresse +His further gate heerein. In that the Leuies, +The Lists, and full proportions are all made +Out of his subiect: and we heere dispatch +You good Cornelius, and you Voltemand, +For bearing of this greeting to old Norway, +Giuing to you no further personall power +To businesse with the King, more then the scope +Of these dilated Articles allow: +Farewell, and let your hast commend your duty + + Volt. In that, and all things, will we shew our duty + + King. We doubt it nothing, heartily farewell. + +Exit Voltemand and Cornelius. + +And now Laertes, what's the newes with you? +You told vs of some suite. What is't Laertes? +You cannot speake of Reason to the Dane, +And loose your voyce. What would'st thou beg Laertes, +That shall not be my Offer, not thy Asking? +The Head is not more Natiue to the Heart, +The Hand more instrumentall to the Mouth, +Then is the Throne of Denmarke to thy Father. +What would'st thou haue Laertes? + Laer. Dread my Lord, +Your leaue and fauour to returne to France, +From whence, though willingly I came to Denmarke +To shew my duty in your Coronation, +Yet now I must confesse, that duty done, +My thoughts and wishes bend againe towards France, +And bow them to your gracious leaue and pardon + + King. Haue you your Fathers leaue? +What sayes Pollonius? + Pol. He hath my Lord: +I do beseech you giue him leaue to go + + King. Take thy faire houre Laertes, time be thine, +And thy best graces spend it at thy will: +But now my Cosin Hamlet, and my Sonne? + Ham. A little more then kin, and lesse then kinde + + King. How is it that the Clouds still hang on you? + Ham. Not so my Lord, I am too much i'th' Sun + + Queen. Good Hamlet cast thy nightly colour off, +And let thine eye looke like a Friend on Denmarke. +Do not for euer with thy veyled lids +Seeke for thy Noble Father in the dust; +Thou know'st 'tis common, all that liues must dye, +Passing through Nature, to Eternity + + Ham. I Madam, it is common + + Queen. If it be; +Why seemes it so particular with thee + + Ham. Seemes Madam? Nay, it is: I know not Seemes: +'Tis not alone my Inky Cloake (good Mother) +Nor Customary suites of solemne Blacke, +Nor windy suspiration of forc'd breath, +No, nor the fruitfull Riuer in the Eye, +Nor the deiected hauiour of the Visage, +Together with all Formes, Moods, shewes of Griefe, +That can denote me truly. These indeed Seeme, +For they are actions that a man might play: +But I haue that Within, which passeth show; +These, but the Trappings, and the Suites of woe + + King. 'Tis sweet and commendable +In your Nature Hamlet, +To giue these mourning duties to your Father: +But you must know, your Father lost a Father, +That Father lost, lost his, and the Suruiuer bound +In filiall Obligation, for some terme +To do obsequious Sorrow. But to perseuer +In obstinate Condolement, is a course +Of impious stubbornnesse. 'Tis vnmanly greefe, +It shewes a will most incorrect to Heauen, +A Heart vnfortified, a Minde impatient, +An Vnderstanding simple, and vnschool'd: +For, what we know must be, and is as common +As any the most vulgar thing to sence, +Why should we in our peeuish Opposition +Take it to heart? Fye, 'tis a fault to Heauen, +A fault against the Dead, a fault to Nature, +To Reason most absurd, whose common Theame +Is death of Fathers, and who still hath cried, +From the first Coarse, till he that dyed to day, +This must be so. We pray you throw to earth +This vnpreuayling woe, and thinke of vs +As of a Father; For let the world take note, +You are the most immediate to our Throne, +And with no lesse Nobility of Loue, +Then that which deerest Father beares his Sonne, +Do I impart towards you. For your intent +In going backe to Schoole in Wittenberg, +It is most retrograde to our desire: +And we beseech you, bend you to remaine +Heere in the cheere and comfort of our eye, +Our cheefest Courtier Cosin, and our Sonne + + Qu. Let not thy Mother lose her Prayers Hamlet: +I prythee stay with vs, go not to Wittenberg + + Ham. I shall in all my best +Obey you Madam + + King. Why 'tis a louing, and a faire Reply, +Be as our selfe in Denmarke. Madam come, +This gentle and vnforc'd accord of Hamlet +Sits smiling to my heart; in grace whereof, +No iocond health that Denmarke drinkes to day, +But the great Cannon to the Clowds shall tell, +And the Kings Rouce, the Heauens shall bruite againe, +Respeaking earthly Thunder. Come away. + +Exeunt. + +Manet Hamlet. + + Ham. Oh that this too too solid Flesh, would melt, +Thaw, and resolue it selfe into a Dew: +Or that the Euerlasting had not fixt +His Cannon 'gainst Selfe-slaughter. O God, O God! +How weary, stale, flat, and vnprofitable +Seemes to me all the vses of this world? +Fie on't? Oh fie, fie, 'tis an vnweeded Garden +That growes to Seed: Things rank, and grosse in Nature +Possesse it meerely. That it should come to this: +But two months dead: Nay, not so much; not two, +So excellent a King, that was to this +Hiperion to a Satyre: so louing to my Mother, +That he might not beteene the windes of heauen +Visit her face too roughly. Heauen and Earth +Must I remember: why she would hang on him, +As if encrease of Appetite had growne +By what is fed on; and yet within a month? +Let me not thinke on't: Frailty, thy name is woman. +A little Month, or ere those shooes were old, +With which she followed my poore Fathers body +Like Niobe, all teares. Why she, euen she. +(O Heauen! A beast that wants discourse of Reason +Would haue mourn'd longer) married with mine Vnkle, +My Fathers Brother: but no more like my Father, +Then I to Hercules. Within a Moneth? +Ere yet the salt of most vnrighteous Teares +Had left the flushing of her gauled eyes, +She married. O most wicked speed, to post +With such dexterity to Incestuous sheets: +It is not, nor it cannot come to good. +But breake my heart, for I must hold my tongue. +Enter Horatio, Barnardo, and Marcellus. + + Hor. Haile to your Lordship + + Ham. I am glad to see you well: +Horatio, or I do forget my selfe + + Hor. The same my Lord, +And your poore Seruant euer + + Ham. Sir my good friend, +Ile change that name with you: +And what make you from Wittenberg Horatio? +Marcellus + + Mar. My good Lord + + Ham. I am very glad to see you: good euen Sir. +But what in faith make you from Wittemberge? + Hor. A truant disposition, good my Lord + + Ham. I would not haue your Enemy say so; +Nor shall you doe mine eare that violence, +To make it truster of your owne report +Against your selfe. I know you are no Truant: +But what is your affaire in Elsenour? +Wee'l teach you to drinke deepe, ere you depart + + Hor. My Lord, I came to see your Fathers Funerall + + Ham. I pray thee doe not mock me (fellow Student) +I thinke it was to see my Mothers Wedding + + Hor. Indeed my Lord, it followed hard vpon + + Ham. Thrift thrift Horatio: the Funerall Bakt-meats +Did coldly furnish forth the Marriage Tables; +Would I had met my dearest foe in heauen, +Ere I had euer seene that day Horatio. +My father, me thinkes I see my father + + Hor. Oh where my Lord? + Ham. In my minds eye (Horatio) + Hor. I saw him once; he was a goodly King + + Ham. He was a man, take him for all in all: +I shall not look vpon his like againe + + Hor. My Lord, I thinke I saw him yesternight + + Ham. Saw? Who? + Hor. My Lord, the King your Father + + Ham. The King my Father? + Hor. Season your admiration for a while +With an attent eare; till I may deliuer +Vpon the witnesse of these Gentlemen, +This maruell to you + + Ham. For Heauens loue let me heare + + Hor. Two nights together, had these Gentlemen +(Marcellus and Barnardo) on their Watch +In the dead wast and middle of the night +Beene thus encountred. A figure like your Father, +Arm'd at all points exactly, Cap a Pe, +Appeares before them, and with sollemne march +Goes slow and stately: By them thrice he walkt, +By their opprest and feare-surprized eyes, +Within his Truncheons length; whilst they bestil'd +Almost to Ielly with the Act of feare, +Stand dumbe and speake not to him. This to me +In dreadfull secrecie impart they did, +And I with them the third Night kept the Watch, +Whereas they had deliuer'd both in time, +Forme of the thing; each word made true and good, +The Apparition comes. I knew your Father: +These hands are not more like + + Ham. But where was this? + Mar. My Lord vpon the platforme where we watcht + + Ham. Did you not speake to it? + Hor. My Lord, I did; +But answere made it none: yet once me thought +It lifted vp it head, and did addresse +It selfe to motion, like as it would speake: +But euen then, the Morning Cocke crew lowd; +And at the sound it shrunke in hast away, +And vanisht from our sight + + Ham. Tis very strange + + Hor. As I doe liue my honourd Lord 'tis true; +And we did thinke it writ downe in our duty +To let you know of it + + Ham. Indeed, indeed Sirs; but this troubles me. +Hold you the watch to Night? + Both. We doe my Lord + + Ham. Arm'd, say you? + Both. Arm'd, my Lord + + Ham. From top to toe? + Both. My Lord, from head to foote + + Ham. Then saw you not his face? + Hor. O yes, my Lord, he wore his Beauer vp + + Ham. What, lookt he frowningly? + Hor. A countenance more in sorrow then in anger + + Ham. Pale, or red? + Hor. Nay very pale + + Ham. And fixt his eyes vpon you? + Hor. Most constantly + + Ham. I would I had beene there + + Hor. It would haue much amaz'd you + + Ham. Very like, very like: staid it long? + Hor. While one with moderate hast might tell a hundred + + All. Longer, longer + + Hor. Not when I saw't + + Ham. His Beard was grisly? no + + Hor. It was, as I haue seene it in his life, +A Sable Siluer'd + + Ham. Ile watch to Night; perchance 'twill wake againe + + Hor. I warrant you it will + + Ham. If it assume my noble Fathers person, +Ile speake to it, though Hell it selfe should gape +And bid me hold my peace. I pray you all, +If you haue hitherto conceald this sight; +Let it bee treble in your silence still: +And whatsoeuer els shall hap to night, +Giue it an vnderstanding but no tongue; +I will requite your loues; so fare ye well: +Vpon the Platforme twixt eleuen and twelue, +Ile visit you + + All. Our duty to your Honour. + +Exeunt + + Ham. Your loue, as mine to you: farewell. +My Fathers Spirit in Armes? All is not well: +I doubt some foule play: would the Night were come; +Till then sit still my soule; foule deeds will rise, +Though all the earth orewhelm them to mens eies. +Enter. + + +Scena Tertia + + +Enter Laertes and Ophelia. + + Laer. My necessaries are imbark't; Farewell: +And Sister, as the Winds giue Benefit, +And Conuoy is assistant; doe not sleepe, +But let me heare from you + + Ophel. Doe you doubt that? + Laer. For Hamlet, and the trifling of his fauours, +Hold it a fashion and a toy in Bloude; +A Violet in the youth of Primy Nature; +Froward, not permanent; sweet not lasting +The suppliance of a minute? No more + + Ophel. No more but so + + Laer. Thinke it no more: +For nature cressant does not grow alone, +In thewes and Bulke: but as his Temple waxes, +The inward seruice of the Minde and Soule +Growes wide withall. Perhaps he loues you now, +And now no soyle nor cautell doth besmerch +The vertue of his feare: but you must feare +His greatnesse weigh'd, his will is not his owne; +For hee himselfe is subiect to his Birth: +Hee may not, as vnuallued persons doe, +Carue for himselfe; for, on his choyce depends +The sanctity and health of the whole State. +And therefore must his choyce be circumscrib'd +Vnto the voyce and yeelding of that Body, +Whereof he is the Head. Then if he sayes he loues you, +It fits your wisedome so farre to beleeue it; +As he in his peculiar Sect and force +May giue his saying deed: which is no further, +Then the maine voyce of Denmarke goes withall. +Then weight what losse your Honour may sustaine, +If with too credent eare you list his Songs; +Or lose your Heart; or your chast Treasure open +To his vnmastred importunity. +Feare it Ophelia, feare it my deare Sister, +And keepe within the reare of your Affection; +Out of the shot and danger of Desire. +The chariest Maid is Prodigall enough, +If she vnmaske her beauty to the Moone: +Vertue it selfe scapes not calumnious stroakes, +The Canker Galls, the Infants of the Spring +Too oft before the buttons be disclos'd, +And in the Morne and liquid dew of Youth, +Contagious blastments are most imminent. +Be wary then, best safety lies in feare; +Youth to it selfe rebels, though none else neere + + Ophe. I shall th' effect of this good Lesson keepe, +As watchmen to my heart: but good my Brother +Doe not as some vngracious Pastors doe, +Shew me the steepe and thorny way to Heauen; +Whilst like a puft and recklesse Libertine +Himselfe, the Primrose path of dalliance treads, +And reaks not his owne reade + + Laer. Oh, feare me not. +Enter Polonius. + +I stay too long; but here my Father comes: +A double blessing is a double grace; +Occasion smiles vpon a second leaue + + Polon. Yet heere Laertes? Aboord, aboord for shame, +The winde sits in the shoulder of your saile, +And you are staid for there: my blessing with you; +And these few Precepts in thy memory, +See thou Character. Giue thy thoughts no tongue, +Nor any vnproportion'd thoughts his Act: +Be thou familiar; but by no meanes vulgar: +The friends thou hast, and their adoption tride, +Grapple them to thy Soule, with hoopes of Steele: +But doe not dull thy palme, with entertainment +Of each vnhatch't, vnfledg'd Comrade. Beware +Of entrance to a quarrell: but being in +Bear't that th' opposed may beware of thee. +Giue euery man thine eare; but few thy voyce: +Take each mans censure; but reserue thy iudgement: +Costly thy habit as thy purse can buy; +But not exprest in fancie; rich, not gawdie: +For the Apparell oft proclaimes the man. +And they in France of the best ranck and station, +Are of a most select and generous cheff in that. +Neither a borrower, nor a lender be; +For lone oft loses both it selfe and friend: +And borrowing duls the edge of Husbandry. +This aboue all; to thine owne selfe be true: +And it must follow, as the Night the Day, +Thou canst not then be false to any man. +Farewell: my Blessing season this in thee + + Laer. Most humbly doe I take my leaue, my Lord + + Polon. The time inuites you, goe, your seruants tend + + Laer. Farewell Ophelia, and remember well +What I haue said to you + + Ophe. Tis in my memory lockt, +And you your selfe shall keepe the key of it + + Laer. Farewell. + +Exit Laer. + + Polon. What ist Ophelia he hath said to you? + Ophe. So please you, somthing touching the L[ord]. Hamlet + + Polon. Marry, well bethought: +Tis told me he hath very oft of late +Giuen priuate time to you; and you your selfe +Haue of your audience beene most free and bounteous. +If it be so, as so tis put on me; +And that in way of caution: I must tell you, +You doe not vnderstand your selfe so cleerely, +As it behoues my Daughter, and your Honour. +What is betweene you, giue me vp the truth? + Ophe. He hath my Lord of late, made many tenders +Of his affection to me + + Polon. Affection, puh. You speake like a greene Girle, +Vnsifted in such perillous Circumstance. +Doe you beleeue his tenders, as you call them? + Ophe. I do not know, my Lord, what I should thinke + + Polon. Marry Ile teach you; thinke your selfe a Baby, +That you haue tane his tenders for true pay, +Which are not starling. Tender your selfe more dearly; +Or not to crack the winde of the poore Phrase, +Roaming it thus, you'l tender me a foole + + Ophe. My Lord, he hath importun'd me with loue, +In honourable fashion + + Polon. I, fashion you may call it, go too, go too + + Ophe. And hath giuen countenance to his speech, +My Lord, with all the vowes of Heauen + + Polon. I, Springes to catch Woodcocks. I doe know +When the Bloud burnes, how Prodigall the Soule +Giues the tongue vowes: these blazes, Daughter, +Giuing more light then heate; extinct in both, +Euen in their promise, as it is a making; +You must not take for fire. For this time Daughter, +Be somewhat scanter of your Maiden presence; +Set your entreatments at a higher rate, +Then a command to parley. For Lord Hamlet, +Beleeue so much in him, that he is young, +And with a larger tether may he walke, +Then may be giuen you. In few, Ophelia, +Doe not beleeue his vowes; for they are Broakers, +Not of the eye, which their Inuestments show: +But meere implorators of vnholy Sutes, +Breathing like sanctified and pious bonds, +The better to beguile. This is for all: +I would not, in plaine tearmes, from this time forth, +Haue you so slander any moment leisure, +As to giue words or talke with the Lord Hamlet: +Looke too't, I charge you; come your wayes + + Ophe. I shall obey my Lord. + +Exeunt. + +Enter Hamlet, Horatio, Marcellus. + + Ham. The Ayre bites shrewdly: is it very cold? + Hor. It is a nipping and an eager ayre + + Ham. What hower now? + Hor. I thinke it lacks of twelue + + Mar. No, it is strooke + + Hor. Indeed I heard it not: then it drawes neere the season, +Wherein the Spirit held his wont to walke. +What does this meane my Lord? + Ham. The King doth wake to night, and takes his rouse, +Keepes wassels and the swaggering vpspring reeles, +And as he dreines his draughts of Renish downe, +The kettle Drum and Trumpet thus bray out +The triumph of his Pledge + + Horat. Is it a custome? + Ham. I marry ist; +And to my mind, though I am natiue heere, +And to the manner borne: It is a Custome +More honour'd in the breach, then the obseruance. +Enter Ghost. + + Hor. Looke my Lord, it comes + + Ham. Angels and Ministers of Grace defend vs: +Be thou a Spirit of health, or Goblin damn'd, +Bring with thee ayres from Heauen, or blasts from Hell, +Be thy euents wicked or charitable, +Thou com'st in such a questionable shape +That I will speake to thee. Ile call thee Hamlet, +King, Father, Royall Dane: Oh, oh, answer me, +Let me not burst in Ignorance; but tell +Why thy Canoniz'd bones Hearsed in death, +Haue burst their cerments, why the Sepulcher +Wherein we saw thee quietly enurn'd, +Hath op'd his ponderous and Marble iawes, +To cast thee vp againe? What may this meane? +That thou dead Coarse againe in compleat steele, +Reuisits thus the glimpses of the Moone, +Making Night hidious? And we fooles of Nature, +So horridly to shake our disposition, +With thoughts beyond thee; reaches of our Soules, +Say, why is this? wherefore? what should we doe? + +Ghost beckens Hamlet. + + Hor. It beckons you to goe away with it, +As if it some impartment did desire +To you alone + + Mar. Looke with what courteous action +It wafts you to a more remoued ground: +But doe not goe with it + + Hor. No, by no meanes + + Ham. It will not speake: then will I follow it + + Hor. Doe not my Lord + + Ham. Why, what should be the feare? +I doe not set my life at a pins fee; +And for my Soule, what can it doe to that? +Being a thing immortall as it selfe: +It waues me forth againe; Ile follow it + + Hor. What if it tempt you toward the Floud my Lord? +Or to the dreadfull Sonnet of the Cliffe, +That beetles o're his base into the Sea, +And there assumes some other horrible forme, +Which might depriue your Soueraignty of Reason, +And draw you into madnesse thinke of it? + Ham. It wafts me still: goe on, Ile follow thee + + Mar. You shall not goe my Lord + + Ham. Hold off your hand + + Hor. Be rul'd, you shall not goe + + Ham. My fate cries out, +And makes each petty Artire in this body, +As hardy as the Nemian Lions nerue: +Still am I cal'd? Vnhand me Gentlemen: +By Heau'n, Ile make a Ghost of him that lets me: +I say away, goe on, Ile follow thee. + +Exeunt. Ghost & Hamlet. + + Hor. He waxes desperate with imagination + + Mar. Let's follow; 'tis not fit thus to obey him + + Hor. Haue after, to what issue will this come? + Mar. Something is rotten in the State of Denmarke + + Hor. Heauen will direct it + + Mar. Nay, let's follow him. + +Exeunt. + +Enter Ghost and Hamlet. + + Ham. Where wilt thou lead me? speak; Ile go no further + + Gho. Marke me + + Ham. I will + + Gho. My hower is almost come, +When I to sulphurous and tormenting Flames +Must render vp my selfe + + Ham. Alas poore Ghost + + Gho. Pitty me not, but lend thy serious hearing +To what I shall vnfold + + Ham. Speake, I am bound to heare + + Gho. So art thou to reuenge, when thou shalt heare + + Ham. What? + Gho. I am thy Fathers Spirit, +Doom'd for a certaine terme to walke the night; +And for the day confin'd to fast in Fiers, +Till the foule crimes done in my dayes of Nature +Are burnt and purg'd away? But that I am forbid +To tell the secrets of my Prison-House; +I could a Tale vnfold, whose lightest word +Would harrow vp thy soule, freeze thy young blood, +Make thy two eyes like Starres, start from their Spheres, +Thy knotty and combined lockes to part, +And each particular haire to stand an end, +Like Quilles vpon the fretfull Porpentine: +But this eternall blason must not be +To eares of flesh and bloud; list Hamlet, oh list, +If thou didst euer thy deare Father loue + + Ham. Oh Heauen! + Gho. Reuenge his foule and most vnnaturall Murther + + Ham. Murther? + Ghost. Murther most foule, as in the best it is; +But this most foule, strange, and vnnaturall + + Ham. Hast, hast me to know it, +That with wings as swift +As meditation, or the thoughts of Loue, +May sweepe to my Reuenge + + Ghost. I finde thee apt, +And duller should'st thou be then the fat weede +That rots it selfe in ease, on Lethe Wharfe, +Would'st thou not stirre in this. Now Hamlet heare: +It's giuen out, that sleeping in mine Orchard, +A Serpent stung me: so the whole eare of Denmarke, +Is by a forged processe of my death +Rankly abus'd: But know thou Noble youth, +The Serpent that did sting thy Fathers life, +Now weares his Crowne + + Ham. O my Propheticke soule: mine Vncle? + Ghost. I that incestuous, that adulterate Beast +With witchcraft of his wits, hath Traitorous guifts. +Oh wicked Wit, and Gifts, that haue the power +So to seduce? Won to this shamefull Lust +The will of my most seeming vertuous Queene: +Oh Hamlet, what a falling off was there, +From me, whose loue was of that dignity, +That it went hand in hand, euen with the Vow +I made to her in Marriage; and to decline +Vpon a wretch, whose Naturall gifts were poore +To those of mine. But Vertue, as it neuer wil be moued, +Though Lewdnesse court it in a shape of Heauen: +So Lust, though to a radiant Angell link'd, +Will sate it selfe in a Celestiall bed, & prey on Garbage. +But soft, me thinkes I sent the Mornings Ayre; +Briefe let me be: Sleeping within mine Orchard, +My custome alwayes in the afternoone; +Vpon my secure hower thy Vncle stole +With iuyce of cursed Hebenon in a Violl, +And in the Porches of mine eares did poure +The leaperous Distilment; whose effect +Holds such an enmity with bloud of Man, +That swift as Quick-siluer, it courses through +The naturall Gates and Allies of the body; +And with a sodaine vigour it doth posset +And curd, like Aygre droppings into Milke, +The thin and wholsome blood: so did it mine; +And a most instant Tetter bak'd about, +Most Lazar-like, with vile and loathsome crust, +All my smooth Body. +Thus was I, sleeping, by a Brothers hand, +Of Life, of Crowne, and Queene at once dispatcht; +Cut off euen in the Blossomes of my Sinne, +Vnhouzzled, disappointed, vnnaneld, +No reckoning made, but sent to my account +With all my imperfections on my head; +Oh horrible Oh horrible, most horrible: +If thou hast nature in thee beare it not; +Let not the Royall Bed of Denmarke be +A Couch for Luxury and damned Incest. +But howsoeuer thou pursuest this Act, +Taint not thy mind; nor let thy Soule contriue +Against thy Mother ought; leaue her to heauen, +And to those Thornes that in her bosome lodge, +To pricke and sting her. Fare thee well at once; +The Glow-worme showes the Matine to be neere, +And gins to pale his vneffectuall Fire: +Adue, adue, Hamlet: remember me. +Enter. + + Ham. Oh all you host of Heauen! Oh Earth; what els? +And shall I couple Hell? Oh fie: hold my heart; +And you my sinnewes, grow not instant Old; +But beare me stiffely vp: Remember thee? +I, thou poore Ghost, while memory holds a seate +In this distracted Globe: Remember thee? +Yea, from the Table of my Memory, +Ile wipe away all triuiall fond Records, +All sawes of Bookes, all formes, all presures past, +That youth and obseruation coppied there; +And thy Commandment all alone shall liue +Within the Booke and Volume of my Braine, +Vnmixt with baser matter; yes yes, by Heauen: +Oh most pernicious woman! +Oh Villaine, Villaine, smiling damned Villaine! +My Tables, my Tables; meet it is I set it downe, +That one may smile, and smile and be a Villaine; +At least I'm sure it may be so in Denmarke; +So Vnckle there you are: now to my word; +It is; Adue, Adue, Remember me: I haue sworn't + + Hor. & Mar. within. My Lord, my Lord. +Enter Horatio and Marcellus. + + Mar. Lord Hamlet + + Hor. Heauen secure him + + Mar. So be it + + Hor. Illo, ho, ho, my Lord + + Ham. Hillo, ho, ho, boy; come bird, come + + Mar. How ist my Noble Lord? + Hor. What newes, my Lord? + Ham. Oh wonderfull! + Hor. Good my Lord tell it + + Ham. No you'l reueale it + + Hor. Not I, my Lord, by Heauen + + Mar. Nor I, my Lord + + Ham. How say you then, would heart of man once think it? +But you'l be secret? + Both. I, by Heau'n, my Lord + + Ham. There's nere a villaine dwelling in all Denmarke +But hee's an arrant knaue + + Hor. There needs no Ghost my Lord, come from the +Graue, to tell vs this + + Ham. Why right, you are i'th' right; +And so, without more circumstance at all, +I hold it fit that we shake hands, and part: +You, as your busines and desires shall point you: +For euery man ha's businesse and desire, +Such as it is: and for mine owne poore part, +Looke you, Ile goe pray + + Hor. These are but wild and hurling words, my Lord + + Ham. I'm sorry they offend you heartily: +Yes faith, heartily + + Hor. There's no offence my Lord + + Ham. Yes, by Saint Patricke, but there is my Lord, +And much offence too, touching this Vision heere: +It is an honest Ghost, that let me tell you: +For your desire to know what is betweene vs, +O'remaster't as you may. And now good friends, +As you are Friends, Schollers and Soldiers, +Giue me one poore request + + Hor. What is't my Lord? we will + + Ham. Neuer make known what you haue seen to night + + Both. My Lord, we will not + + Ham. Nay, but swear't + + Hor. Infaith my Lord, not I + + Mar. Nor I my Lord: in faith + + Ham. Vpon my sword + + Marcell. We haue sworne my Lord already + + Ham. Indeed, vpon my sword, Indeed + + Gho. Sweare. + +Ghost cries vnder the Stage. + + Ham. Ah ha boy, sayest thou so. Art thou there truepenny? +Come one you here this fellow in the selleredge +Consent to sweare + + Hor. Propose the Oath my Lord + + Ham. Neuer to speake of this that you haue seene. +Sweare by my sword + + Gho. Sweare + + Ham. Hic & vbique? Then wee'l shift for grownd, +Come hither Gentlemen, +And lay your hands againe vpon my sword, +Neuer to speake of this that you haue heard: +Sweare by my Sword + + Gho. Sweare + + Ham. Well said old Mole, can'st worke i'th' ground so fast? +A worthy Pioner, once more remoue good friends + + Hor. Oh day and night: but this is wondrous strange + + Ham. And therefore as a stranger giue it welcome. +There are more things in Heauen and Earth, Horatio, +Then are dream't of in our Philosophy. But come, +Here as before, neuer so helpe you mercy, +How strange or odde so ere I beare my selfe; +(As I perchance heereafter shall thinke meet +To put an Anticke disposition on:) +That you at such time seeing me, neuer shall +With Armes encombred thus, or thus, head shake; +Or by pronouncing of some doubtfull Phrase; +As well, we know, or we could and if we would, +Or if we list to speake; or there be and if there might, +Or such ambiguous giuing out to note, +That you know ought of me; this not to doe: +So grace and mercy at your most neede helpe you: +Sweare + + Ghost. Sweare + + Ham. Rest, rest perturbed Spirit: so Gentlemen, +With all my loue I doe commend me to you; +And what so poore a man as Hamlet is, +May doe t' expresse his loue and friending to you, +God willing shall not lacke: let vs goe in together, +And still your fingers on your lippes I pray, +The time is out of ioynt: Oh cursed spight, +That euer I was borne to set it right. +Nay, come let's goe together. + +Exeunt. + + +Actus Secundus. + +Enter Polonius, and Reynoldo. + + Polon. Giue him his money, and these notes Reynoldo + + Reynol. I will my Lord + + Polon. You shall doe maruels wisely: good Reynoldo, +Before you visite him you make inquiry +Of his behauiour + + Reynol. My Lord, I did intend it + + Polon. Marry, well said; +Very well said. Looke you Sir, +Enquire me first what Danskers are in Paris; +And how, and who; what meanes; and where they keepe: +What company, at what expence: and finding +By this encompassement and drift of question, +That they doe know my sonne: Come you more neerer +Then your particular demands will touch it, +Take you as 'twere some distant knowledge of him, +And thus I know his father and his friends, +And in part him. Doe you marke this Reynoldo? + Reynol. I, very well my Lord + + Polon. And in part him, but you may say not well; +But if't be hee I meane, hees very wilde; +Addicted so and so; and there put on him +What forgeries you please; marry, none so ranke, +As may dishonour him; take heed of that: +But Sir, such wanton, wild, and vsuall slips, +As are Companions noted and most knowne +To youth and liberty + + Reynol. As gaming my Lord + + Polon. I, or drinking, fencing, swearing, +Quarelling, drabbing. You may goe so farre + + Reynol. My Lord that would dishonour him + + Polon. Faith no, as you may season it in the charge; +You must not put another scandall on him, +That hee is open to Incontinencie; +That's not my meaning: but breath his faults so quaintly, +That they may seeme the taints of liberty; +The flash and out-breake of a fiery minde, +A sauagenes in vnreclaim'd bloud of generall assault + + Reynol. But my good Lord + + Polon. Wherefore should you doe this? + Reynol. I my Lord, I would know that + + Polon. Marry Sir, heere's my drift, +And I belieue it is a fetch of warrant: +You laying these slight sulleyes on my Sonne, +As 'twere a thing a little soil'd i'th' working: +Marke you your party in conuerse; him you would sound, +Hauing euer seene. In the prenominate crimes, +The youth you breath of guilty, be assur'd +He closes with you in this consequence: +Good sir, or so, or friend, or Gentleman. +According to the Phrase and the Addition, +Of man and Country + + Reynol. Very good my Lord + + Polon. And then Sir does he this? +He does: what was I about to say? +I was about say somthing: where did I leaue? + Reynol. At closes in the consequence: +At friend, or so, and Gentleman + + Polon. At closes in the consequence, I marry, +He closes with you thus. I know the Gentleman, +I saw him yesterday, or tother day; +Or then or then, with such and such; and as you say, +There was he gaming, there o'retooke in's Rouse, +There falling out at Tennis; or perchance, +I saw him enter such a house of saile; +Videlicet, a Brothell, or so forth. See you now; +Your bait of falshood, takes this Cape of truth; +And thus doe we of wisedome and of reach +With windlesses, and with assaies of Bias, +By indirections finde directions out: +So by my former Lecture and aduice +Shall you my Sonne; you haue me, haue you not? + Reynol. My Lord I haue + + Polon. God buy you; fare you well + + Reynol. Good my Lord + + Polon. Obserue his inclination in your selfe + + Reynol. I shall my Lord + + Polon. And let him plye his Musicke + + Reynol. Well, my Lord. +Enter. + +Enter Ophelia. + + Polon. Farewell: +How now Ophelia, what's the matter? + Ophe. Alas my Lord, I haue beene so affrighted + + Polon. With what, in the name of Heauen? + Ophe. My Lord, as I was sowing in my Chamber, +Lord Hamlet with his doublet all vnbrac'd, +No hat vpon his head, his stockings foul'd, +Vngartred, and downe giued to his Anckle, +Pale as his shirt, his knees knocking each other, +And with a looke so pitious in purport, +As if he had been loosed out of hell, +To speake of horrors: he comes before me + + Polon. Mad for thy Loue? + Ophe. My Lord, I doe not know: but truly I do feare it + + Polon. What said he? + Ophe. He tooke me by the wrist, and held me hard; +Then goes he to the length of all his arme; +And with his other hand thus o're his brow, +He fals to such perusall of my face, +As he would draw it. Long staid he so, +At last, a little shaking of mine Arme: +And thrice his head thus wauing vp and downe; +He rais'd a sigh, so pittious and profound, +That it did seeme to shatter all his bulke, +And end his being. That done, he lets me goe, +And with his head ouer his shoulders turn'd, +He seem'd to finde his way without his eyes, +For out adores he went without their helpe; +And to the last, bended their light on me + + Polon. Goe with me, I will goe seeke the King, +This is the very extasie of Loue, +Whose violent property foredoes it selfe, +And leads the will to desperate Vndertakings, +As oft as any passion vnder Heauen, +That does afflict our Natures. I am sorrie, +What haue you giuen him any hard words of late? + Ophe. No my good Lord: but as you did command, +I did repell his Letters, and deny'de +His accesse to me + + Pol. That hath made him mad. +I am sorrie that with better speed and iudgement +I had not quoted him. I feare he did but trifle, +And meant to wracke thee: but beshrew my iealousie: +It seemes it is as proper to our Age, +To cast beyond our selues in our Opinions, +As it is common for the yonger sort +To lacke discretion. Come, go we to the King, +This must be knowne, being kept close might moue +More greefe to hide, then hate to vtter loue. + +Exeunt. + + +Scena Secunda. + +Enter King, Queene, Rosincrane, and Guildensterne Cum alijs. + + King. Welcome deere Rosincrance and Guildensterne. +Moreouer, that we much did long to see you, +The neede we haue to vse you, did prouoke +Our hastie sending. Something haue you heard +Of Hamlets transformation: so I call it, +Since not th' exterior, nor the inward man +Resembles that it was. What it should bee +More then his Fathers death, that thus hath put him +So much from th' vnderstanding of himselfe, +I cannot deeme of. I intreat you both, +That being of so young dayes brought vp with him: +And since so Neighbour'd to his youth, and humour, +That you vouchsafe your rest heere in our Court +Some little time: so by your Companies +To draw him on to pleasures, and to gather +So much as from Occasions you may gleane, +That open'd lies within our remedie + + Qu. Good Gentlemen, he hath much talk'd of you, +And sure I am, two men there are not liuing, +To whom he more adheres. If it will please you +To shew vs so much Gentrie, and good will, +As to expend your time with vs a-while, +For the supply and profit of our Hope, +Your Visitation shall receiue such thankes +As fits a Kings remembrance + + Rosin. Both your Maiesties +Might by the Soueraigne power you haue of vs, +Put your dread pleasures, more into Command +Then to Entreatie + + Guil. We both obey, +And here giue vp our selues, in the full bent, +To lay our Seruices freely at your feete, +To be commanded + + King. Thankes Rosincrance, and gentle Guildensterne + + Qu. Thankes Guildensterne and gentle Rosincrance. +And I beseech you instantly to visit +My too much changed Sonne. +Go some of ye, +And bring the Gentlemen where Hamlet is + + Guil. Heauens make our presence and our practises +Pleasant and helpfull to him. +Enter. + + Queene. Amen. +Enter Polonius. + + Pol. Th' Ambassadors from Norwey, my good Lord, +Are ioyfully return'd + + King. Thou still hast bin the father of good Newes + + Pol. Haue I, my Lord? Assure you, my good Liege, +I hold my dutie, as I hold my Soule, +Both to my God, one to my gracious King: +And I do thinke, or else this braine of mine +Hunts not the traile of Policie, so sure +As I haue vs'd to do: that I haue found +The very cause of Hamlets Lunacie + + King. Oh speake of that, that I do long to heare + + Pol. Giue first admittance to th' Ambassadors, +My Newes shall be the Newes to that great Feast + + King. Thy selfe do grace to them, and bring them in. +He tels me my sweet Queene, that he hath found +The head and sourse of all your Sonnes distemper + + Qu. I doubt it is no other, but the maine, +His Fathers death, and our o're-hasty Marriage. +Enter Polonius, Voltumand, and Cornelius. + + King. Well, we shall sift him. Welcome good Frends: +Say Voltumand, what from our Brother Norwey? + Volt. Most faire returne of Greetings, and Desires. +Vpon our first, he sent out to suppresse +His Nephewes Leuies, which to him appear'd +To be a preparation 'gainst the Poleak: +But better look'd into, he truly found +It was against your Highnesse, whereat greeued, +That so his Sicknesse, Age, and Impotence +Was falsely borne in hand, sends out Arrests +On Fortinbras, which he (in breefe) obeyes, +Receiues rebuke from Norwey: and in fine, +Makes Vow before his Vnkle, neuer more +To giue th' assay of Armes against your Maiestie. +Whereon old Norwey, ouercome with ioy, +Giues him three thousand Crownes in Annuall Fee, +And his Commission to imploy those Soldiers +So leuied as before, against the Poleak: +With an intreaty heerein further shewne, +That it might please you to giue quiet passe +Through your Dominions, for his Enterprize, +On such regards of safety and allowance, +As therein are set downe + + King. It likes vs well: +And at our more consider'd time wee'l read, +Answer, and thinke vpon this Businesse. +Meane time we thanke you, for your well-tooke Labour. +Go to your rest, at night wee'l Feast together. +Most welcome home. + +Exit Ambass. + + Pol. This businesse is very well ended. +My Liege, and Madam, to expostulate +What Maiestie should be, what Dutie is, +Why day is day; night, night; and time is time, +Were nothing but to waste Night, Day, and Time. +Therefore, since Breuitie is the Soule of Wit, +And tediousnesse, the limbes and outward flourishes, +I will be breefe. Your Noble Sonne is mad: +Mad call I it; for to define true Madnesse, +What is't, but to be nothing else but mad. +But let that go + + Qu. More matter, with lesse Art + + Pol. Madam, I sweare I vse no Art at all: +That he is mad, 'tis true: 'Tis true 'tis pittie, +And pittie it is true: A foolish figure, +But farewell it: for I will vse no Art. +Mad let vs grant him then: and now remaines +That we finde out the cause of this effect, +Or rather say, the cause of this defect; +For this effect defectiue, comes by cause, +Thus it remaines, and the remainder thus. Perpend, +I haue a daughter: haue, whil'st she is mine, +Who in her Dutie and Obedience, marke, +Hath giuen me this: now gather, and surmise. + +The Letter. + +To the Celestiall, and my Soules Idoll, the most beautifed Ophelia. +That's an ill Phrase, a vilde Phrase, beautified is a vilde +Phrase: but you shall heare these in her excellent white +bosome, these + + Qu. Came this from Hamlet to her + + Pol. Good Madam stay awhile, I will be faithfull. +Doubt thou, the Starres are fire, +Doubt, that the Sunne doth moue: +Doubt Truth to be a Lier, +But neuer Doubt, I loue. +O deere Ophelia, I am ill at these Numbers: I haue not Art to +reckon my grones; but that I loue thee best, oh most Best beleeue +it. Adieu. +Thine euermore most deere Lady, whilst this +Machine is to him, Hamlet. +This in Obedience hath my daughter shew'd me: +And more aboue hath his soliciting, +As they fell out by Time, by Meanes, and Place, +All giuen to mine eare + + King. But how hath she receiu'd his Loue? + Pol. What do you thinke of me? + King. As of a man, faithfull and Honourable + + Pol. I wold faine proue so. But what might you think? +When I had seene this hot loue on the wing, +As I perceiued it, I must tell you that +Before my Daughter told me what might you +Or my deere Maiestie your Queene heere, think, +If I had playd the Deske or Table-booke, +Or giuen my heart a winking, mute and dumbe, +Or look'd vpon this Loue, with idle sight, +What might you thinke? No, I went round to worke, +And (my yong Mistris) thus I did bespeake +Lord Hamlet is a Prince out of thy Starre, +This must not be: and then, I Precepts gaue her, +That she should locke her selfe from his Resort, +Admit no Messengers, receiue no Tokens: +Which done, she tooke the Fruites of my Aduice, +And he repulsed. A short Tale to make, +Fell into a Sadnesse, then into a Fast, +Thence to a Watch, thence into a Weaknesse, +Thence to a Lightnesse, and by this declension +Into the Madnesse whereon now he raues, +And all we waile for + + King. Do you thinke 'tis this? + Qu. It may be very likely + + Pol. Hath there bene such a time, I'de fain know that, +That I haue possitiuely said, 'tis so, +When it prou'd otherwise? + King. Not that I know + + Pol. Take this from this; if this be otherwise, +If Circumstances leade me, I will finde +Where truth is hid, though it were hid indeede +Within the Center + + King. How may we try it further? + Pol. You know sometimes +He walkes foure houres together, heere +In the Lobby + + Qu. So he ha's indeed + + Pol. At such a time Ile loose my Daughter to him, +Be you and I behinde an Arras then, +Marke the encounter: If he loue her not, +And be not from his reason falne thereon; +Let me be no Assistant for a State, +And keepe a Farme and Carters + + King. We will try it. +Enter Hamlet reading on a Booke. + + Qu. But looke where sadly the poore wretch +Comes reading + + Pol. Away I do beseech you, both away, +Ile boord him presently. + +Exit King & Queen. + +Oh giue me leaue. How does my good Lord Hamlet? + Ham. Well, God-a-mercy + + Pol. Do you know me, my Lord? + Ham. Excellent, excellent well: y'are a Fishmonger + + Pol. Not I my Lord + + Ham. Then I would you were so honest a man + + Pol. Honest, my Lord? + Ham. I sir, to be honest as this world goes, is to bee +one man pick'd out of two thousand + + Pol. That's very true, my Lord + + Ham. For if the Sun breed Magots in a dead dogge, +being a good kissing Carrion- +Haue you a daughter? + Pol. I haue my Lord + + Ham. Let her not walke i'thSunne: Conception is a +blessing, but not as your daughter may conceiue. Friend +looke too't + + Pol. How say you by that? Still harping on my daughter: +yet he knew me not at first; he said I was a Fishmonger: +he is farre gone, farre gone: and truly in my youth, +I suffred much extreamity for loue: very neere this. Ile +speake to him againe. What do you read my Lord? + Ham. Words, words, words + + Pol. What is the matter, my Lord? + Ham. Betweene who? + Pol. I meane the matter you meane, my Lord + + Ham. Slanders Sir: for the Satyricall slaue saies here, +that old men haue gray Beards; that their faces are wrinkled; +their eyes purging thicke Amber, or Plum-Tree +Gumme: and that they haue a plentifull locke of Wit, +together with weake Hammes. All which Sir, though I +most powerfully, and potently beleeue; yet I holde it +not Honestie to haue it thus set downe: For you your +selfe Sir, should be old as I am, if like a Crab you could +go backward + + Pol. Though this be madnesse, +Yet there is Method in't: will you walke +Out of the ayre my Lord? + Ham. Into my Graue? + Pol. Indeed that is out o'th' Ayre: +How pregnant (sometimes) his Replies are? +A happinesse, +That often Madnesse hits on, +Which Reason and Sanitie could not +So prosperously be deliuer'd of. +I will leaue him, +And sodainely contriue the meanes of meeting +Betweene him, and my daughter. +My Honourable Lord, I will most humbly +Take my leaue of you + + Ham. You cannot Sir take from me any thing, that I +will more willingly part withall, except my life, my +life + + Polon. Fare you well my Lord + + Ham. These tedious old fooles + + Polon. You goe to seeke my Lord Hamlet; there +hee is. +Enter Rosincran and Guildensterne. + + Rosin. God saue you Sir + + Guild. Mine honour'd Lord? + Rosin. My most deare Lord? + Ham. My excellent good friends? How do'st thou +Guildensterne? Oh, Rosincrane; good Lads: How doe ye +both? + Rosin. As the indifferent Children of the earth + + Guild. Happy, in that we are not ouer-happy: on Fortunes +Cap, we are not the very Button + + Ham. Nor the Soales of her Shoo? + Rosin. Neither my Lord + + Ham. Then you liue about her waste, or in the middle +of her fauour? + Guil. Faith, her priuates, we + + Ham. In the secret parts of Fortune? Oh, most true: +she is a Strumpet. What's the newes? + Rosin. None my Lord; but that the World's growne +honest + + Ham. Then is Doomesday neere: But your newes is +not true. Let me question more in particular: what haue +you my good friends, deserued at the hands of Fortune, +that she sends you to Prison hither? + Guil. Prison, my Lord? + Ham. Denmark's a Prison + + Rosin. Then is the World one + + Ham. A goodly one, in which there are many Confines, +Wards, and Dungeons; Denmarke being one o'th' +worst + + Rosin. We thinke not so my Lord + + Ham. Why then 'tis none to you; for there is nothing +either good or bad, but thinking makes it so: to me it is +a prison + + Rosin. Why then your Ambition makes it one: 'tis +too narrow for your minde + + Ham. O God, I could be bounded in a nutshell, and +count my selfe a King of infinite space; were it not that +I haue bad dreames + + Guil. Which dreames indeed are Ambition: for the +very substance of the Ambitious, is meerely the shadow +of a Dreame + + Ham. A dreame it selfe is but a shadow + + Rosin. Truely, and I hold Ambition of so ayry and +light a quality, that it is but a shadowes shadow + + Ham. Then are our Beggers bodies; and our Monarchs +and out-stretcht Heroes the Beggers Shadowes: +shall wee to th' Court: for, by my fey I cannot reason? + Both. Wee'l wait vpon you + + Ham. No such matter. I will not sort you with the +rest of my seruants: for to speake to you like an honest +man: I am most dreadfully attended; but in the beaten +way of friendship, What make you at Elsonower? + Rosin. To visit you my Lord, no other occasion + + Ham. Begger that I am, I am euen poore in thankes; +but I thanke you: and sure deare friends my thanks +are too deare a halfepeny; were you not sent for? Is it +your owne inclining? Is it a free visitation? Come, +deale iustly with me: come, come; nay speake + + Guil. What should we say my Lord? + Ham. Why any thing. But to the purpose; you were +sent for; and there is a kinde confession in your lookes; +which your modesties haue not craft enough to color, +I know the good King & Queene haue sent for you + + Rosin. To what end my Lord? + Ham. That you must teach me: but let mee coniure +you by the rights of our fellowship, by the consonancy of +our youth, by the Obligation of our euer-preserued loue, +and by what more deare, a better proposer could charge +you withall; be euen and direct with me, whether you +were sent for or no + + Rosin. What say you? + Ham. Nay then I haue an eye of you: if you loue me +hold not off + + Guil. My Lord, we were sent for + + Ham. I will tell you why; so shall my anticipation +preuent your discouery of your secricie to the King and +Queene: moult no feather, I haue of late, but wherefore +I know not, lost all my mirth, forgone all custome of exercise; +and indeed, it goes so heauenly with my disposition; +that this goodly frame the Earth, seemes to me a sterrill +Promontory; this most excellent Canopy the Ayre, +look you, this braue ore-hanging, this Maiesticall Roofe, +fretted with golden fire: why, it appeares no other thing +to mee, then a foule and pestilent congregation of vapours. +What a piece of worke is a man! how Noble in +Reason? how infinite in faculty? in forme and mouing +how expresse and admirable? in Action, how like an Angel? +in apprehension, how like a God? the beauty of the +world, the Parragon of Animals; and yet to me, what is +this Quintessence of Dust? Man delights not me; no, +nor Woman neither; though by your smiling you seeme +to say so + + Rosin. My Lord, there was no such stuffe in my +thoughts + + Ham. Why did you laugh, when I said, Man delights +not me? + Rosin. To thinke, my Lord, if you delight not in Man, +what Lenton entertainment the Players shall receiue +from you: wee coated them on the way, and hither are +they comming to offer you Seruice + + Ham. He that playes the King shall be welcome; his +Maiesty shall haue Tribute of mee: the aduenturous +Knight shal vse his Foyle and Target: the Louer shall +not sigh gratis, the humorous man shall end his part in +peace: the Clowne shall make those laugh whose lungs +are tickled a'th' sere: and the Lady shall say her minde +freely; or the blanke Verse shall halt for't: what Players +are they? + Rosin. Euen those you were wont to take delight in +the Tragedians of the City + + Ham. How chances it they trauaile? their residence +both in reputation and profit was better both +wayes + + Rosin. I thinke their Inhibition comes by the meanes +of the late Innouation? + Ham. Doe they hold the same estimation they did +when I was in the City? Are they so follow'd? + Rosin. No indeed, they are not + + Ham. How comes it? doe they grow rusty? + Rosin. Nay, their indeauour keepes in the wonted +pace; But there is Sir an ayrie of Children, little +Yases, that crye out on the top of question; and +are most tyrannically clap't for't: these are now the +fashion, and so be-ratled the common Stages (so they +call them) that many wearing Rapiers, are affraide of +Goose-quils, and dare scarse come thither + + Ham. What are they Children? Who maintains 'em? +How are they escorted? Will they pursue the Quality no +longer then they can sing? Will they not say afterwards +if they should grow themselues to common Players (as +it is most like if their meanes are not better) their Writers +do them wrong, to make them exclaim against their +owne Succession + + Rosin. Faith there ha's bene much to do on both sides: +and the Nation holds it no sinne, to tarre them to Controuersie. +There was for a while, no mony bid for argument, +vnlesse the Poet and the Player went to Cuffes in +the Question + + Ham. Is't possible? + Guild. Oh there ha's beene much throwing about of +Braines + + Ham. Do the Boyes carry it away? + Rosin. I that they do my Lord. Hercules & his load too + + Ham. It is not strange: for mine Vnckle is King of +Denmarke, and those that would make mowes at him +while my Father liued; giue twenty, forty, an hundred +Ducates a peece, for his picture in Little. There is something +in this more then Naturall, if Philosophie could +finde it out. + +Flourish for the Players. + + Guil. There are the Players + + Ham. Gentlemen, you are welcom to Elsonower: your +hands, come: The appurtenance of Welcome, is Fashion +and Ceremony. Let me comply with you in the Garbe, +lest my extent to the Players (which I tell you must shew +fairely outward) should more appeare like entertainment +then yours. You are welcome: but my Vnckle Father, +and Aunt Mother are deceiu'd + + Guil. In what my deere Lord? + Ham. I am but mad North, North-West: when the +Winde is Southerly, I know a Hawke from a Handsaw. +Enter Polonius. + + Pol. Well be with you Gentlemen + + Ham. Hearke you Guildensterne, and you too: at each +eare a hearer: that great Baby you see there, is not yet +out of his swathing clouts + + Rosin. Happily he's the second time come to them: for +they say, an old man is twice a childe + + Ham. I will Prophesie. Hee comes to tell me of the +Players. Mark it, you say right Sir: for a Monday morning +'twas so indeed + + Pol. My Lord, I haue Newes to tell you + + Ham. My Lord, I haue Newes to tell you. +When Rossius an Actor in Rome- + Pol. The Actors are come hither my Lord + + Ham. Buzze, buzze + + Pol. Vpon mine Honor + + Ham. Then can each Actor on his Asse- + Polon. The best Actors in the world, either for Tragedie, +Comedie, Historie, Pastorall: +Pastoricall-Comicall-Historicall-Pastorall: +Tragicall-Historicall: Tragicall-Comicall-Historicall-Pastorall: +Scene indiuidible: or Poem +vnlimited. Seneca cannot be too heauy, nor Plautus +too light, for the law of Writ, and the Liberty. These are +the onely men + + Ham. O Iephta Iudge of Israel, what a Treasure had'st +thou? + Pol. What a Treasure had he, my Lord? + Ham. Why one faire Daughter, and no more, +The which he loued passing well + + Pol. Still on my Daughter + + Ham. Am I not i'th' right old Iephta? + Polon. If you call me Iephta my Lord, I haue a daughter +that I loue passing well + + Ham. Nay that followes not + + Polon. What followes then, my Lord? + Ha. Why, As by lot, God wot: and then you know, It +came to passe, as most like it was: The first rowe of the +Pons Chanson will shew you more. For looke where my +Abridgements come. +Enter foure or fiue Players. + +Y'are welcome Masters, welcome all. I am glad to see +thee well: Welcome good Friends. Oh my olde Friend? +Thy face is valiant since I saw thee last: Com'st thou to +beard me in Denmarke? What, my yong Lady and Mistris? +Byrlady your Ladiship is neerer Heauen then when +I saw you last, by the altitude of a Choppine. Pray God +your voice like a peece of vncurrant Gold be not crack'd +within the ring. Masters, you are all welcome: wee'l e'ne +to't like French Faulconers, flie at any thing we see: wee'l +haue a Speech straight. Come giue vs a tast of your quality: +come, a passionate speech + + 1.Play. What speech, my Lord? + Ham. I heard thee speak me a speech once, but it was +neuer Acted: or if it was, not aboue once, for the Play I +remember pleas'd not the Million, 'twas Cauiarie to the +Generall: but it was (as I receiu'd it, and others, whose +iudgement in such matters, cried in the top of mine) an +excellent Play; well digested in the Scoenes, set downe +with as much modestie, as cunning. I remember one said, +there was no Sallets in the lines, to make the matter sauory; +nor no matter in the phrase, that might indite the +Author of affectation, but cal'd it an honest method. One +cheefe Speech in it, I cheefely lou'd, 'twas Aeneas Tale +to Dido, and thereabout of it especially, where he speaks +of Priams slaughter. If it liue in your memory, begin at +this Line, let me see, let me see: The rugged Pyrrhus like +th'Hyrcanian Beast. It is not so: it begins with Pyrrhus +The rugged Pyrrhus, he whose Sable Armes +Blacke as his purpose, did the night resemble +When he lay couched in the Ominous Horse, +Hath now this dread and blacke Complexion smear'd +With Heraldry more dismall: Head to foote +Now is he to take Geulles, horridly Trick'd +With blood of Fathers, Mothers, Daughters, Sonnes, +Bak'd and impasted with the parching streets, +That lend a tyrannous, and damned light +To their vilde Murthers, roasted in wrath and fire, +And thus o're-sized with coagulate gore, +With eyes like Carbuncles, the hellish Pyrrhus +Olde Grandsire Priam seekes + + Pol. Fore God, my Lord, well spoken, with good accent, +and good discretion + + 1.Player. Anon he findes him, +Striking too short at Greekes. His anticke Sword, +Rebellious to his Arme, lyes where it falles +Repugnant to command: vnequall match, +Pyrrhus at Priam driues, in Rage strikes wide: +But with the whiffe and winde of his fell Sword, +Th' vnnerued Father fals. Then senselesse Illium, +Seeming to feele his blow, with flaming top +Stoopes to his Bace, and with a hideous crash +Takes Prisoner Pyrrhus eare. For loe, his Sword +Which was declining on the Milkie head +Of Reuerend Priam, seem'd i'th' Ayre to sticke: +So as a painted Tyrant Pyrrhus stood, +And like a Newtrall to his will and matter, did nothing. +But as we often see against some storme, +A silence in the Heauens, the Racke stand still, +The bold windes speechlesse, and the Orbe below +As hush as death: Anon the dreadfull Thunder +Doth rend the Region. So after Pyrrhus pause, +A rowsed Vengeance sets him new a-worke, +And neuer did the Cyclops hammers fall +On Mars his Armours, forg'd for proofe Eterne, +With lesse remorse then Pyrrhus bleeding sword +Now falles on Priam. +Out, out, thou Strumpet-Fortune, all you Gods, +In generall Synod take away her power: +Breake all the Spokes and Fallies from her wheele, +And boule the round Naue downe the hill of Heauen, +As low as to the Fiends + + Pol. This is too long + + Ham. It shall to'th Barbars, with your beard. Prythee +say on: He's for a Iigge, or a tale of Baudry, or hee +sleepes. Say on; come to Hecuba + + 1.Play. But who, O who, had seen the inobled Queen + + Ham. The inobled Queene? + Pol. That's good: Inobled Queene is good + + 1.Play. Run bare-foot vp and downe, +Threatning the flame +With Bisson Rheume: A clout about that head, +Where late the Diadem stood, and for a Robe +About her lanke and all ore-teamed Loines, +A blanket in th' Alarum of feare caught vp. +Who this had seene, with tongue in Venome steep'd, +'Gainst Fortunes State, would Treason haue pronounc'd? +But if the Gods themselues did see her then, +When she saw Pyrrhus make malicious sport +In mincing with his Sword her Husbands limbes, +The instant Burst of Clamour that she made +(Vnlesse things mortall moue them not at all) +Would haue made milche the Burning eyes of Heauen, +And passion in the Gods + + Pol. Looke where he ha's not turn'd his colour, and +ha's teares in's eyes. Pray you no more + + Ham. 'Tis well, Ile haue thee speake out the rest, +soone. Good my Lord, will you see the Players wel bestow'd. +Do ye heare, let them be well vs'd: for they are +the Abstracts and breefe Chronicles of the time. After +your death, you were better haue a bad Epitaph, then +their ill report while you liued + + Pol. My Lord, I will vse them according to their desart + + Ham. Gods bodykins man, better. Vse euerie man +after his desart, and who should scape whipping: vse +them after your own Honor and Dignity. The lesse they +deserue, the more merit is in your bountie. Take them +in + + Pol. Come sirs. + +Exit Polon. + + Ham. Follow him Friends: wee'l heare a play to morrow. +Dost thou heare me old Friend, can you play the +murther of Gonzago? + Play. I my Lord + + Ham. Wee'l ha't to morrow night. You could for a +need study a speech of some dosen or sixteene lines, which +I would set downe, and insert in't? Could ye not? + Play. I my Lord + + Ham. Very well. Follow that Lord, and looke you +mock him not. My good Friends, Ile leaue you til night +you are welcome to Elsonower? + Rosin. Good my Lord. + +Exeunt. + +Manet Hamlet. + + Ham. I so, God buy'ye: Now I am alone. +Oh what a Rogue and Pesant slaue am I? +Is it not monstrous that this Player heere, +But in a Fixion, in a dreame of Passion, +Could force his soule so to his whole conceit, +That from her working, all his visage warm'd; +Teares in his eyes, distraction in's Aspect, +A broken voyce, and his whole Function suiting +With Formes, to his Conceit? And all for nothing? +For Hecuba? +What's Hecuba to him, or he to Hecuba, +That he should weepe for her? What would he doe, +Had he the Motiue and the Cue for passion +That I haue? He would drowne the Stage with teares, +And cleaue the generall eare with horrid speech: +Make mad the guilty, and apale the free, +Confound the ignorant, and amaze indeed, +The very faculty of Eyes and Eares. Yet I, +A dull and muddy-metled Rascall, peake +Like Iohn a-dreames, vnpregnant of my cause, +And can say nothing: No, not for a King, +Vpon whose property, and most deere life, +A damn'd defeate was made. Am I a Coward? +Who calles me Villaine? breakes my pate a-crosse? +Pluckes off my Beard, and blowes it in my face? +Tweakes me by'th' Nose? giues me the Lye i'th' Throate, +As deepe as to the Lungs? Who does me this? +Ha? Why I should take it: for it cannot be, +But I am Pigeon-Liuer'd, and lacke Gall +To make Oppression bitter, or ere this, +I should haue fatted all the Region Kites +With this Slaues Offall, bloudy: a Bawdy villaine, +Remorselesse, Treacherous, Letcherous, kindles villaine! +Oh Vengeance! +Who? What an Asse am I? I sure, this is most braue, +That I, the Sonne of the Deere murthered, +Prompted to my Reuenge by Heauen, and Hell, +Must (like a Whore) vnpacke my heart with words, +And fall a Cursing like a very Drab. +A Scullion? Fye vpon't: Foh. About my Braine. +I haue heard, that guilty Creatures sitting at a Play, +Haue by the very cunning of the Scoene, +Bene strooke so to the soule, that presently +They haue proclaim'd their Malefactions. +For Murther, though it haue no tongue, will speake +With most myraculous Organ. Ile haue these Players, +Play something like the murder of my Father, +Before mine Vnkle. Ile obserue his lookes, +Ile rent him to the quicke: If he but blench +I know my course. The Spirit that I haue seene +May be the Diuell, and the Diuel hath power +T' assume a pleasing shape, yea and perhaps +Out of my Weaknesse, and my Melancholly, +As he is very potent with such Spirits, +Abuses me to damne me. Ile haue grounds +More Relatiue then this: The Play's the thing, +Wherein Ile catch the Conscience of the King. + +Exit + +Enter King, Queene, Polonius, Ophelia, Rosincrance, +Guildenstern, and +Lords. + + King. And can you by no drift of circumstance +Get from him why he puts on this Confusion: +Grating so harshly all his dayes of quiet +With turbulent and dangerous Lunacy + + Rosin. He does confesse he feeles himselfe distracted, +But from what cause he will by no meanes speake + + Guil. Nor do we finde him forward to be sounded, +But with a crafty Madnesse keepes aloofe: +When we would bring him on to some Confession +Of his true state + + Qu. Did he receiue you well? + Rosin. Most like a Gentleman + + Guild. But with much forcing of his disposition + + Rosin. Niggard of question, but of our demands +Most free in his reply + + Qu. Did you assay him to any pastime? + Rosin. Madam, it so fell out, that certaine Players +We ore-wrought on the way: of these we told him, +And there did seeme in him a kinde of ioy +To heare of it: They are about the Court, +And (as I thinke) they haue already order +This night to play before him + + Pol. 'Tis most true: +And he beseech'd me to intreate your Maiesties +To heare, and see the matter + + King. With all my heart, and it doth much content me +To heare him so inclin'd. Good Gentlemen, +Giue him a further edge, and driue his purpose on +To these delights + + Rosin. We shall my Lord. + +Exeunt. + + King. Sweet Gertrude leaue vs too, +For we haue closely sent for Hamlet hither, +That he, as 'twere by accident, may there +Affront Ophelia. Her Father, and my selfe (lawful espials) +Will so bestow our selues, that seeing vnseene +We may of their encounter frankely iudge, +And gather by him, as he is behaued, +If't be th' affliction of his loue, or no. +That thus he suffers for + + Qu. I shall obey you, +And for your part Ophelia, I do wish +That your good Beauties be the happy cause +Of Hamlets wildenesse: so shall I hope your Vertues +Will bring him to his wonted way againe, +To both your Honors + + Ophe. Madam, I wish it may + + Pol. Ophelia, walke you heere. Gracious so please ye +We will bestow our selues: Reade on this booke, +That shew of such an exercise may colour +Your lonelinesse. We are oft too blame in this, +'Tis too much prou'd, that with Deuotions visage, +And pious Action, we do surge o're +The diuell himselfe + + King. Oh 'tis true: +How smart a lash that speech doth giue my Conscience? +The Harlots Cheeke beautied with plaist'ring Art +Is not more vgly to the thing that helpes it, +Then is my deede, to my most painted word. +Oh heauie burthen! + Pol. I heare him comming, let's withdraw my Lord. + +Exeunt. + +Enter Hamlet. + + Ham. To be, or not to be, that is the Question: +Whether 'tis Nobler in the minde to suffer +The Slings and Arrowes of outragious Fortune, +Or to take Armes against a Sea of troubles, +And by opposing end them: to dye, to sleepe +No more; and by a sleepe, to say we end +The Heart-ake, and the thousand Naturall shockes +That Flesh is heyre too? 'Tis a consummation +Deuoutly to be wish'd. To dye to sleepe, +To sleepe, perchance to Dreame; I, there's the rub, +For in that sleepe of death, what dreames may come, +When we haue shuffel'd off this mortall coile, +Must giue vs pawse. There's the respect +That makes Calamity of so long life: +For who would beare the Whips and Scornes of time, +The Oppressors wrong, the poore mans Contumely, +The pangs of dispriz'd Loue, the Lawes delay, +The insolence of Office, and the Spurnes +That patient merit of the vnworthy takes, +When he himselfe might his Quietus make +With a bare Bodkin? Who would these Fardles beare +To grunt and sweat vnder a weary life, +But that the dread of something after death, +The vndiscouered Countrey, from whose Borne +No Traueller returnes, Puzels the will, +And makes vs rather beare those illes we haue, +Then flye to others that we know not of. +Thus Conscience does make Cowards of vs all, +And thus the Natiue hew of Resolution +Is sicklied o're, with the pale cast of Thought, +And enterprizes of great pith and moment, +With this regard their Currants turne away, +And loose the name of Action. Soft you now, +The faire Ophelia? Nimph, in thy Orizons +Be all my sinnes remembred + + Ophe. Good my Lord, +How does your Honor for this many a day? + Ham. I humbly thanke you: well, well, well + + Ophe. My Lord, I haue Remembrances of yours, +That I haue longed long to re-deliuer. +I pray you now, receiue them + + Ham. No, no, I neuer gaue you ought + + Ophe. My honor'd Lord, I know right well you did, +And with them words of so sweet breath compos'd, +As made the things more rich, then perfume left: +Take these againe, for to the Noble minde +Rich gifts wax poore, when giuers proue vnkinde. +There my Lord + + Ham. Ha, ha: Are you honest? + Ophe. My Lord + + Ham. Are you faire? + Ophe. What meanes your Lordship? + Ham. That if you be honest and faire, your Honesty +should admit no discourse to your Beautie + + Ophe. Could Beautie my Lord, haue better Comerce +then your Honestie? + Ham. I trulie: for the power of Beautie, will sooner +transforme Honestie from what is, to a Bawd, then the +force of Honestie can translate Beautie into his likenesse. +This was sometime a Paradox, but now the time giues it +proofe. I did loue you once + + Ophe. Indeed my Lord, you made me beleeue so + + Ham. You should not haue beleeued me. For vertue +cannot so innocculate our old stocke, but we shall rellish +of it. I loued you not + + Ophe. I was the more deceiued + + Ham. Get thee to a Nunnerie. Why would'st thou +be a breeder of Sinners? I am my selfe indifferent honest, +but yet I could accuse me of such things, that it were better +my Mother had not borne me. I am very prowd, reuengefull, +Ambitious, with more offences at my becke, +then I haue thoughts to put them in imagination, to giue +them shape, or time to acte them in. What should such +Fellowes as I do, crawling betweene Heauen and Earth. +We are arrant Knaues all, beleeue none of vs. Goe thy +wayes to a Nunnery. Where's your Father? + Ophe. At home, my Lord + + Ham. Let the doores be shut vpon him, that he may +play the Foole no way, but in's owne house. Farewell + + Ophe. O helpe him, you sweet Heauens + + Ham. If thou doest Marry, Ile giue thee this Plague +for thy Dowrie. Be thou as chast as Ice, as pure as Snow, +thou shalt not escape Calumny. Get thee to a Nunnery. +Go, Farewell. Or if thou wilt needs Marry, marry a fool: +for Wise men know well enough, what monsters you +make of them. To a Nunnery go, and quickly too. Farwell + + Ophe. O heauenly Powers, restore him + + Ham. I haue heard of your pratlings too wel enough. +God has giuen you one pace, and you make your selfe another: +you gidge, you amble, and you lispe, and nickname +Gods creatures, and make your Wantonnesse, your Ignorance. +Go too, Ile no more on't, it hath made me mad. +I say, we will haue no more Marriages. Those that are +married already, all but one shall liue, the rest shall keep +as they are. To a Nunnery, go. + +Exit Hamlet. + + Ophe. O what a Noble minde is heere o're-throwne? +The Courtiers, Soldiers, Schollers: Eye, tongue, sword, +Th' expectansie and Rose of the faire State, +The glasse of Fashion, and the mould of Forme, +Th' obseru'd of all Obseruers, quite, quite downe. +Haue I of Ladies most deiect and wretched, +That suck'd the Honie of his Musicke Vowes: +Now see that Noble, and most Soueraigne Reason, +Like sweet Bels iangled out of tune, and harsh, +That vnmatch'd Forme and Feature of blowne youth, +Blasted with extasie. Oh woe is me, +T'haue seene what I haue seene: see what I see. +Enter King, and Polonius. + + King. Loue? His affections do not that way tend, +Nor what he spake, though it lack'd Forme a little, +Was not like Madnesse. There's something in his soule? +O're which his Melancholly sits on brood, +And I do doubt the hatch, and the disclose +Will be some danger, which to preuent +I haue in quicke determination +Thus set it downe. He shall with speed to England +For the demand of our neglected Tribute: +Haply the Seas and Countries different +With variable Obiects, shall expell +This something setled matter in his heart: +Whereon his Braines still beating, puts him thus +From fashion of himselfe. What thinke you on't? + Pol. It shall do well. But yet do I beleeue +The Origin and Commencement of this greefe +Sprung from neglected loue. How now Ophelia? +You neede not tell vs, what Lord Hamlet saide, +We heard it all. My Lord, do as you please, +But if you hold it fit after the Play, +Let his Queene Mother all alone intreat him +To shew his Greefes: let her be round with him, +And Ile be plac'd so, please you in the eare +Of all their Conference. If she finde him not, +To England send him: Or confine him where +Your wisedome best shall thinke + + King. It shall be so: +Madnesse in great Ones, must not vnwatch'd go. + +Exeunt. + +Enter Hamlet, and two or three of the Players. + + Ham. Speake the Speech I pray you, as I pronounc'd +it to you trippingly on the Tongue: But if you mouth it, +as many of your Players do, I had as liue the Town-Cryer +had spoke my Lines: Nor do not saw the Ayre too much +your hand thus, but vse all gently; for in the verie Torrent, +Tempest, and (as I say) the Whirle-winde of +Passion, you must acquire and beget a Temperance that +may giue it Smoothnesse. O it offends mee to the Soule, +to see a robustious Pery-wig-pated Fellow, teare a Passion +to tatters, to verie ragges, to split the eares of the +Groundlings: who (for the most part) are capeable of +nothing, but inexplicable dumbe shewes, & noise: I could +haue such a Fellow whipt for o're-doing Termagant: it +outHerod's Herod. Pray you auoid it + + Player. I warrant your Honor + + Ham. Be not too tame neyther: but let your owne +Discretion be your Tutor. Sute the Action to the Word, +the Word to the Action, with this speciall obseruance: +That you ore-stop not the modestie of Nature; for any +thing so ouer-done, is fro[m] the purpose of Playing, whose +end both at the first and now, was and is, to hold as 'twer +the Mirrour vp to Nature; to shew Vertue her owne +Feature, Scorne her owne Image, and the verie Age and +Bodie of the Time, his forme and pressure. Now, this +ouer-done, or come tardie off, though it make the vnskilfull +laugh, cannot but make the Iudicious greeue; The +censure of the which One, must in your allowance o'reway +a whole Theater of Others. Oh, there bee Players +that I haue seene Play, and heard others praise, and that +highly (not to speake it prophanely) that neyther hauing +the accent of Christians, nor the gate of Christian, Pagan, +or Norman, haue so strutted and bellowed, that I haue +thought some of Natures Iouerney-men had made men, +and not made them well, they imitated Humanity so abhominably + + Play. I hope we haue reform'd that indifferently with +vs, Sir + + Ham. O reforme it altogether. And let those that +play your Clownes, speake no more then is set downe for +them. For there be of them, that will themselues laugh, +to set on some quantitie of barren Spectators to laugh +too, though in the meane time, some necessary Question +of the Play be then to be considered: that's Villanous, & +shewes a most pittifull Ambition in the Foole that vses +it. Go make you readie. + +Exit Players. + +Enter Polonius, Rosincrance, and Guildensterne. + +How now my Lord, +Will the King heare this peece of Worke? + Pol. And the Queene too, and that presently + + Ham. Bid the Players make hast. + +Exit Polonius. + +Will you two helpe to hasten them? + Both. We will my Lord. + +Exeunt. + +Enter Horatio. + + Ham. What hoa, Horatio? + Hora. Heere sweet Lord, at your Seruice + + Ham. Horatio, thou art eene as iust a man +As ere my Conuersation coap'd withall + + Hora. O my deere Lord + + Ham. Nay, do not thinke I flatter: +For what aduancement may I hope from thee, +That no Reuennew hast, but thy good spirits +To feed & cloath thee. Why shold the poor be flatter'd? +No, let the Candied tongue, like absurd pompe, +And crooke the pregnant Hindges of the knee, +Where thrift may follow faining? Dost thou heare, +Since my deere Soule was Mistris of my choyse, +And could of men distinguish, her election +Hath seal'd thee for her selfe. For thou hast bene +As one in suffering all, that suffers nothing. +A man that Fortunes buffets, and Rewards +Hath 'tane with equall Thankes. And blest are those, +Whose Blood and Iudgement are so well co-mingled, +That they are not a Pipe for Fortunes finger. +To sound what stop she please. Giue me that man, +That is not Passions Slaue, and I will weare him +In my hearts Core. I, in my Heart of heart, +As I do thee. Something too much of this. +There is a Play to night to before the King. +One Scoene of it comes neere the Circumstance +Which I haue told thee, of my Fathers death. +I prythee, when thou see'st that Acte a-foot, +Euen with the verie Comment of my Soule +Obserue mine Vnkle: If his occulted guilt, +Do not it selfe vnkennell in one speech, +It is a damned Ghost that we haue seene: +And my Imaginations are as foule +As Vulcans Stythe. Giue him needfull note, +For I mine eyes will riuet to his Face: +And after we will both our iudgements ioyne, +To censure of his seeming + + Hora. Well my Lord. +If he steale ought the whil'st this Play is Playing, +And scape detecting, I will pay the Theft. +Enter King, Queene, Polonius, Ophelia, Rosincrance, +Guildensterne, and +other Lords attendant with his Guard carrying Torches. Danish +March. Sound +a Flourish. + + Ham. They are comming to the Play: I must be idle. +Get you a place + + King. How fares our Cosin Hamlet? + Ham. Excellent Ifaith, of the Camelions dish: I eate +the Ayre promise-cramm'd, you cannot feed Capons so + + King. I haue nothing with this answer Hamlet, these +words are not mine + + Ham. No, nor mine. Now my Lord, you plaid once +i'th' Vniuersity, you say? + Polon. That I did my Lord, and was accounted a good +Actor + + Ham. And what did you enact? + Pol. I did enact Iulius Caesar, I was kill'd i'th' Capitol: +Brutus kill'd me + + Ham. It was a bruite part of him, to kill so Capitall a +Calfe there. Be the Players ready? + Rosin. I my Lord, they stay vpon your patience + + Qu. Come hither my good Hamlet, sit by me + + Ha. No good Mother, here's Mettle more attractiue + + Pol. Oh ho, do you marke that? + Ham. Ladie, shall I lye in your Lap? + Ophe. No my Lord + + Ham. I meane, my Head vpon your Lap? + Ophe. I my Lord + + Ham. Do you thinke I meant Country matters? + Ophe. I thinke nothing, my Lord + + Ham. That's a faire thought to ly betweene Maids legs + Ophe. What is my Lord? + Ham. Nothing + + Ophe. You are merrie, my Lord? + Ham. Who I? + Ophe. I my Lord + + Ham. Oh God, your onely Iigge-maker: what should +a man do, but be merrie. For looke you how cheerefully +my Mother lookes, and my Father dyed within's two +Houres + + Ophe. Nay, 'tis twice two moneths, my Lord + + Ham. So long? Nay then let the Diuel weare blacke, +for Ile haue a suite of Sables. Oh Heauens! dye two moneths +ago, and not forgotten yet? Then there's hope, a +great mans Memorie, may out-liue his life halfe a yeare: +But byrlady he must builde Churches then: or else shall +he suffer not thinking on, with the Hoby-horsse, whose +Epitaph is, For o, For o, the Hoby-horse is forgot. + +Hoboyes play. The dumbe shew enters. + +Enter a King and Queene, very louingly; the Queene embracing +him. She +kneeles, and makes shew of Protestation vnto him. He takes her +vp, and +declines his head vpon her neck. Layes him downe vpon a Banke +of Flowers. +She seeing him a-sleepe, leaues him. Anon comes in a Fellow, +takes off his +Crowne, kisses it, and powres poyson in the Kings eares, and +Exits. The +Queene returnes, findes the King dead, and makes passionate +Action. The +Poysoner, with some two or three Mutes comes in againe, seeming +to lament +with her. The dead body is carried away: The Poysoner Wooes the +Queene with +Gifts, she seemes loath and vnwilling awhile, but in the end, +accepts his +loue. + +Exeunt. + + Ophe. What meanes this, my Lord? + Ham. Marry this is Miching Malicho, that meanes +Mischeefe + + Ophe. Belike this shew imports the Argument of the +Play? + Ham. We shall know by these Fellowes: the Players +cannot keepe counsell, they'l tell all + + Ophe. Will they tell vs what this shew meant? + Ham. I, or any shew that you'l shew him. Bee not +you asham'd to shew, hee'l not shame to tell you what it +meanes + + Ophe. You are naught, you are naught, Ile marke the +Play. +Enter Prologue. + +For vs, and for our Tragedie, +Heere stooping to your Clemencie: +We begge your hearing Patientlie + + Ham. Is this a Prologue, or the Poesie of a Ring? + Ophe. 'Tis briefe my Lord + + Ham. As Womans loue. +Enter King and his Queene. + + King. Full thirtie times hath Phoebus Cart gon round, +Neptunes salt Wash, and Tellus Orbed ground: +And thirtie dozen Moones with borrowed sheene, +About the World haue times twelue thirties beene, +Since loue our hearts, and Hymen did our hands +Vnite comutuall, in most sacred Bands + + Bap. So many iournies may the Sunne and Moone +Make vs againe count o're, ere loue be done. +But woe is me, you are so sicke of late, +So farre from cheere, and from your former state, +That I distrust you: yet though I distrust, +Discomfort you (my Lord) it nothing must: +For womens Feare and Loue, holds quantitie, +In neither ought, or in extremity: +Now what my loue is, proofe hath made you know, +And as my Loue is siz'd, my Feare is so + + King. Faith I must leaue thee Loue, and shortly too: +My operant Powers my Functions leaue to do: +And thou shalt liue in this faire world behinde, +Honour'd, belou'd, and haply, one as kinde. +For Husband shalt thou- + Bap. Oh confound the rest: +Such Loue, must needs be Treason in my brest: +In second Husband, let me be accurst, +None wed the second, but who kill'd the first + + Ham. Wormwood, Wormwood + + Bapt. The instances that second Marriage moue, +Are base respects of Thrift, but none of Loue. +A second time, I kill my Husband dead, +When second Husband kisses me in Bed + + King. I do beleeue you. Think what now you speak: +But what we do determine, oft we breake: +Purpose is but the slaue to Memorie, +Of violent Birth, but poore validitie: +Which now like Fruite vnripe stickes on the Tree, +But fall vnshaken, when they mellow bee. +Most necessary 'tis, that we forget +To pay our selues, what to our selues is debt: +What to our selues in passion we propose, +The passion ending, doth the purpose lose. +The violence of other Greefe or Ioy, +Their owne ennactors with themselues destroy: +Where Ioy most Reuels, Greefe doth most lament; +Greefe ioyes, Ioy greeues on slender accident. +This world is not for aye, nor 'tis not strange +That euen our Loues should with our Fortunes change. +For 'tis a question left vs yet to proue, +Whether Loue lead Fortune, or else Fortune Loue. +The great man downe, you marke his fauourites flies, +The poore aduanc'd, makes Friends of Enemies: +And hitherto doth Loue on Fortune tend, +For who not needs, shall neuer lacke a Frend: +And who in want a hollow Friend doth try, +Directly seasons him his Enemie. +But orderly to end, where I begun, +Our Willes and Fates do so contrary run, +That our Deuices still are ouerthrowne, +Our thoughts are ours, their ends none of our owne. +So thinke thou wilt no second Husband wed. +But die thy thoughts, when thy first Lord is dead + + Bap. Nor Earth to giue me food, nor Heauen light, +Sport and repose locke from me day and night: +Each opposite that blankes the face of ioy, +Meet what I would haue well, and it destroy: +Both heere, and hence, pursue me lasting strife, +If once a Widdow, euer I be Wife + + Ham. If she should breake it now + + King. 'Tis deepely sworne: +Sweet, leaue me heere a while, +My spirits grow dull, and faine I would beguile +The tedious day with sleepe + + Qu. Sleepe rocke thy Braine, + +Sleepes + +And neuer come mischance betweene vs twaine. + +Exit + + Ham. Madam, how like you this Play? + Qu. The Lady protests to much me thinkes + + Ham. Oh but shee'l keepe her word + + King. Haue you heard the Argument, is there no Offence +in't? + Ham. No, no, they do but iest, poyson in iest, no Offence +i'th' world + + King. What do you call the Play? + Ham. The Mouse-trap: Marry how? Tropically: +This Play is the Image of a murder done in Vienna: Gonzago +is the Dukes name, his wife Baptista: you shall see +anon: 'tis a knauish peece of worke: But what o'that? +Your Maiestie, and wee that haue free soules, it touches +vs not: let the gall'd iade winch: our withers are vnrung. +Enter Lucianus. + +This is one Lucianus nephew to the King + + Ophe. You are a good Chorus, my Lord + + Ham. I could interpret betweene you and your loue: +if I could see the Puppets dallying + + Ophe. You are keene my Lord, you are keene + + Ham. It would cost you a groaning, to take off my +edge + + Ophe. Still better and worse + + Ham. So you mistake Husbands. +Begin Murderer. Pox, leaue thy damnable Faces, and +begin. Come, the croaking Rauen doth bellow for Reuenge + + Lucian. Thoughts blacke, hands apt, +Drugges fit, and Time agreeing: +Confederate season, else, no Creature seeing: +Thou mixture ranke, of Midnight Weeds collected, +With Hecats Ban, thrice blasted, thrice infected, +Thy naturall Magicke, and dire propertie, +On wholsome life, vsurpe immediately. + +Powres the poyson in his eares. + + Ham. He poysons him i'th' Garden for's estate: His +name's Gonzago: the Story is extant and writ in choyce +Italian. You shall see anon how the Murtherer gets the +loue of Gonzago's wife + + Ophe. The King rises + + Ham. What, frighted with false fire + + Qu. How fares my Lord? + Pol. Giue o're the Play + + King. Giue me some Light. Away + + All. Lights, Lights, Lights. + +Exeunt. + +Manet Hamlet & Horatio. + + Ham. Why let the strucken Deere go weepe, +The Hart vngalled play: +For some must watch, while some must sleepe; +So runnes the world away. +Would not this Sir, and a Forrest of Feathers, if the rest of +my Fortunes turne Turke with me; with two Prouinciall +Roses on my rac'd Shooes, get me a Fellowship in a crie +of Players sir + + Hor. Halfe a share + + Ham. A whole one I, +For thou dost know: Oh Damon deere, +This Realme dismantled was of Ioue himselfe, +And now reignes heere. +A verie verie Paiocke + + Hora. You might haue Rim'd + + Ham. Oh good Horatio, Ile take the Ghosts word for +a thousand pound. Did'st perceiue? + Hora. Verie well my Lord + + Ham. Vpon the talke of the poysoning? + Hora. I did verie well note him. +Enter Rosincrance and Guildensterne. + + Ham. Oh, ha? Come some Musick. Come y Recorders: +For if the King like not the Comedie, +Why then belike he likes it not perdie. +Come some Musicke + + Guild. Good my Lord, vouchsafe me a word with you + + Ham. Sir, a whole History + + Guild. The King, sir + + Ham. I sir, what of him? + Guild. Is in his retyrement, maruellous distemper'd + + Ham. With drinke Sir? + Guild. No my Lord, rather with choller + + Ham. Your wisedome should shew it selfe more richer, +to signifie this to his Doctor: for for me to put him +to his Purgation, would perhaps plundge him into farre +more Choller + + Guild. Good my Lord put your discourse into some +frame, and start not so wildely from my affayre + + Ham. I am tame Sir, pronounce + + Guild. The Queene your Mother, in most great affliction +of spirit, hath sent me to you + + Ham. You are welcome + + Guild. Nay, good my Lord, this courtesie is not of +the right breed. If it shall please you to make me a wholsome +answer, I will doe your Mothers command'ment: +if not, your pardon, and my returne shall bee the end of +my Businesse + + Ham. Sir, I cannot + + Guild. What, my Lord? + Ham. Make you a wholsome answere: my wits diseas'd. +But sir, such answers as I can make, you shal command: +or rather you say, my Mother: therfore no more +but to the matter. My Mother you say + + Rosin. Then thus she sayes: your behauior hath stroke +her into amazement, and admiration + + Ham. Oh wonderfull Sonne, that can so astonish a +Mother. But is there no sequell at the heeles of this Mothers +admiration? + Rosin. She desires to speake with you in her Closset, +ere you go to bed + + Ham. We shall obey, were she ten times our Mother. +Haue you any further Trade with vs? + Rosin. My Lord, you once did loue me + + Ham. So I do still, by these pickers and stealers + + Rosin. Good my Lord, what is your cause of distemper? +You do freely barre the doore of your owne Libertie, +if you deny your greefes to your Friend + + Ham. Sir I lacke Aduancement + + Rosin. How can that be, when you haue the voyce of +the King himselfe, for your Succession in Denmarke? + Ham. I, but while the grasse growes, the Prouerbe is +something musty. +Enter one with a Recorder. + +O the Recorder. Let me see, to withdraw with you, why +do you go about to recouer the winde of mee, as if you +would driue me into a toyle? + Guild. O my Lord, if my Dutie be too bold, my loue +is too vnmannerly + + Ham. I do not well vnderstand that. Will you play +vpon this Pipe? + Guild. My Lord, I cannot + + Ham. I pray you + + Guild. Beleeue me, I cannot + + Ham. I do beseech you + + Guild. I know no touch of it, my Lord + + Ham. 'Tis as easie as lying: gouerne these Ventiges +with your finger and thumbe, giue it breath with your +mouth, and it will discourse most excellent Musicke. +Looke you, these are the stoppes + + Guild. But these cannot I command to any vtterance +of hermony, I haue not the skill + + Ham. Why looke you now, how vnworthy a thing +you make of me: you would play vpon mee; you would +seeme to know my stops: you would pluck out the heart +of my Mysterie; you would sound mee from my lowest +Note, to the top of my Compasse: and there is much Musicke, +excellent Voice, in this little Organe, yet cannot +you make it. Why do you thinke, that I am easier to bee +plaid on, then a Pipe? Call me what Instrument you will, +though you can fret me, you cannot play vpon me. God +blesse you Sir. +Enter Polonius. + + Polon. My Lord; the Queene would speak with you, +and presently + + Ham. Do you see that Clowd? that's almost in shape +like a Camell + + Polon. By'th' Masse, and it's like a Camell indeed + + Ham. Me thinkes it is like a Weazell + + Polon. It is back'd like a Weazell + + Ham. Or like a Whale? + Polon. Verie like a Whale + + Ham. Then will I come to my Mother, by and by: +They foole me to the top of my bent. +I will come by and by + + Polon. I will say so. +Enter. + + Ham. By and by, is easily said. Leaue me Friends: +'Tis now the verie witching time of night, +When Churchyards yawne, and Hell it selfe breaths out +Contagion to this world. Now could I drink hot blood, +And do such bitter businesse as the day +Would quake to looke on. Soft now, to my Mother: +Oh Heart, loose not thy Nature; let not euer +The Soule of Nero, enter this firme bosome: +Let me be cruell, not vnnaturall, +I will speake Daggers to her, but vse none: +My Tongue and Soule in this be Hypocrites. +How in my words someuer she be shent, +To giue them Seales, neuer my Soule consent. +Enter King, Rosincrance, and Guildensterne. + + King. I like him not, nor stands it safe with vs, +To let his madnesse range. Therefore prepare you, +I your Commission will forthwith dispatch, +And he to England shall along with you: +The termes of our estate, may not endure +Hazard so dangerous as doth hourely grow +Out of his Lunacies + + Guild. We will our selues prouide: +Most holie and Religious feare it is +To keepe those many many bodies safe +That liue and feede vpon your Maiestie + + Rosin. The single +And peculiar life is bound +With all the strength and Armour of the minde, +To keepe it selfe from noyance: but much more, +That Spirit, vpon whose spirit depends and rests +The liues of many, the cease of Maiestie +Dies not alone; but like a Gulfe doth draw +What's neere it, with it. It is a massie wheele +Fixt on the Somnet of the highest Mount. +To whose huge Spoakes, ten thousand lesser things +Are mortiz'd and adioyn'd: which when it falles, +Each small annexment, pettie consequence +Attends the boystrous Ruine. Neuer alone +Did the King sighe, but with a generall grone + + King. Arme you, I pray you to this speedie Voyage; +For we will Fetters put vpon this feare, +Which now goes too free-footed + + Both. We will haste vs. + +Exeunt. Gent. + +Enter Polonius. + + Pol. My Lord, he's going to his Mothers Closset: +Behinde the Arras Ile conuey my selfe +To heare the Processe. Ile warrant shee'l tax him home, +And as you said, and wisely was it said, +'Tis meete that some more audience then a Mother, +Since Nature makes them partiall, should o're-heare +The speech of vantage. Fare you well my Liege, +Ile call vpon you ere you go to bed, +And tell you what I know + + King. Thankes deere my Lord. +Oh my offence is ranke, it smels to heauen, +It hath the primall eldest curse vpon't, +A Brothers murther. Pray can I not, +Though inclination be as sharpe as will: +My stronger guilt, defeats my strong intent, +And like a man to double businesse bound, +I stand in pause where I shall first begin, +And both neglect; what if this cursed hand +Were thicker then it selfe with Brothers blood, +Is there not Raine enough in the sweet Heauens +To wash it white as Snow? Whereto serues mercy, +But to confront the visage of Offence? +And what's in Prayer, but this two-fold force, +To be fore-stalled ere we come to fall, +Or pardon'd being downe? Then Ile looke vp, +My fault is past. But oh, what forme of Prayer +Can serue my turne? Forgiue me my foule Murther: +That cannot be, since I am still possest +Of those effects for which I did the Murther. +My Crowne, mine owne Ambition, and my Queene: +May one be pardon'd, and retaine th' offence? +In the corrupted currants of this world, +Offences gilded hand may shoue by Iustice, +And oft 'tis seene, the wicked prize it selfe +Buyes out the Law; but 'tis not so aboue, +There is no shuffling, there the Action lyes +In his true Nature, and we our selues compell'd +Euen to the teeth and forehead of our faults, +To giue in euidence. What then? What rests? +Try what Repentance can. What can it not? +Yet what can it, when one cannot repent? +Oh wretched state! Oh bosome, blacke as death! +Oh limed soule, that strugling to be free, +Art more ingag'd: Helpe Angels, make assay: +Bow stubborne knees, and heart with strings of Steele, +Be soft as sinewes of the new-borne Babe, +All may be well. +Enter Hamlet. + + Ham. Now might I do it pat, now he is praying, +And now Ile doo't, and so he goes to Heauen, +And so am I reueng'd: that would be scann'd, +A Villaine killes my Father, and for that +I his foule Sonne, do this same Villaine send +To heauen. Oh this is hyre and Sallery, not Reuenge. +He tooke my Father grossely, full of bread, +With all his Crimes broad blowne, as fresh as May, +And how his Audit stands, who knowes, saue Heauen: +But in our circumstance and course of thought +'Tis heauie with him: and am I then reueng'd, +To take him in the purging of his Soule, +When he is fit and season'd for his passage? No. +Vp Sword, and know thou a more horrid hent +When he is drunke asleepe: or in his Rage, +Or in th' incestuous pleasure of his bed, +At gaming, swearing, or about some acte +That ha's no rellish of Saluation in't, +Then trip him, that his heeles may kicke at Heauen, +And that his Soule may be as damn'd and blacke +As Hell, whereto it goes. My Mother stayes, +This Physicke but prolongs thy sickly dayes. +Enter. + + King. My words flye vp, my thoughts remain below, +Words without thoughts, neuer to Heauen go. +Enter. + +Enter Queene and Polonius. + + Pol. He will come straight: +Looke you lay home to him, +Tell him his prankes haue been too broad to beare with, +And that your Grace hath screen'd, and stoode betweene +Much heate, and him. Ile silence me e'ene heere: +Pray you be round with him + + Ham. within. Mother, mother, mother + + Qu. Ile warrant you, feare me not. +Withdraw, I heare him coming. +Enter Hamlet. + + Ham. Now Mother, what's the matter? + Qu. Hamlet, thou hast thy Father much offended + + + Ham. Mother, you haue my Father much offended + + Qu. Come, come, you answer with an idle tongue + + Ham. Go, go, you question with an idle tongue + + Qu. Why how now Hamlet? + Ham. Whats the matter now? + Qu. Haue you forgot me? + Ham. No by the Rood, not so: +You are the Queene, your Husbands Brothers wife, +But would you were not so. You are my Mother + + Qu. Nay, then Ile set those to you that can speake + + Ham. Come, come, and sit you downe, you shall not +boudge: +You go not till I set you vp a glasse, +Where you may see the inmost part of you? + Qu. What wilt thou do? thou wilt not murther me? +Helpe, helpe, hoa + + Pol. What hoa, helpe, helpe, helpe + + Ham. How now, a Rat? dead for a Ducate, dead + + Pol. Oh I am slaine. + +Killes Polonius + + Qu. Oh me, what hast thou done? + Ham. Nay I know not, is it the King? + Qu. Oh what a rash, and bloody deed is this? + Ham. A bloody deed, almost as bad good Mother, +As kill a King, and marrie with his Brother + + Qu. As kill a King? + Ham. I Lady, 'twas my word. +Thou wretched, rash, intruding foole farewell, +I tooke thee for thy Betters, take thy Fortune, +Thou find'st to be too busie, is some danger. +Leaue wringing of your hands, peace, sit you downe, +And let me wring your heart, for so I shall +If it be made of penetrable stuffe; +If damned Custome haue not braz'd it so, +That it is proofe and bulwarke against Sense + + Qu. What haue I done, that thou dar'st wag thy tong, +In noise so rude against me? + Ham. Such an Act +That blurres the grace and blush of Modestie, +Cals Vertue Hypocrite, takes off the Rose +From the faire forehead of an innocent loue, +And makes a blister there. Makes marriage vowes +As false as Dicers Oathes. Oh such a deed, +As from the body of Contraction pluckes +The very soule, and sweete Religion makes +A rapsidie of words. Heauens face doth glow, +Yea this solidity and compound masse, +With tristfull visage as against the doome, +Is thought-sicke at the act + + Qu. Aye me; what act, that roares so lowd, & thunders +in the Index + + Ham. Looke heere vpon this Picture, and on this, +The counterfet presentment of two Brothers: +See what a grace was seated on his Brow, +Hyperions curles, the front of Ioue himselfe, +An eye like Mars, to threaten or command +A Station, like the Herald Mercurie +New lighted on a heauen-kissing hill: +A Combination, and a forme indeed, +Where euery God did seeme to set his Seale, +To giue the world assurance of a man. +This was your Husband. Looke you now what followes. +Heere is your Husband, like a Mildew'd eare +Blasting his wholsom breath. Haue you eyes? +Could you on this faire Mountaine leaue to feed, +And batten on this Moore? Ha? Haue you eyes? +You cannot call it Loue: For at your age, +The hey-day in the blood is tame, it's humble, +And waites vpon the Iudgement: and what Iudgement +Would step from this, to this? What diuell was't, +That thus hath cousend you at hoodman-blinde? +O Shame! where is thy Blush? Rebellious Hell, +If thou canst mutine in a Matrons bones, +To flaming youth, let Vertue be as waxe. +And melt in her owne fire. Proclaime no shame, +When the compulsiue Ardure giues the charge, +Since Frost it selfe, as actiuely doth burne, +As Reason panders Will + + Qu. O Hamlet, speake no more. +Thou turn'st mine eyes into my very soule, +And there I see such blacke and grained spots, +As will not leaue their Tinct + + Ham. Nay, but to liue +In the ranke sweat of an enseamed bed, +Stew'd in Corruption; honying and making loue +Ouer the nasty Stye + + Qu. Oh speake to me, no more, +These words like Daggers enter in mine eares. +No more sweet Hamlet + + Ham. A Murderer, and a Villaine: +A Slaue, that is not twentieth part the tythe +Of your precedent Lord. A vice of Kings, +A Cutpurse of the Empire and the Rule. +That from a shelfe, the precious Diadem stole, +And put it in his Pocket + + Qu. No more. +Enter Ghost. + + Ham. A King of shreds and patches. +Saue me; and houer o're me with your wings +You heauenly Guards. What would your gracious figure? + Qu. Alas he's mad + + Ham. Do you not come your tardy Sonne to chide, +That laps't in Time and Passion, lets go by +Th' important acting of your dread command? Oh say + + Ghost. Do not forget: this Visitation +Is but to whet thy almost blunted purpose. +But looke, Amazement on thy Mother sits; +O step betweene her, and her fighting Soule, +Conceit in weakest bodies, strongest workes. +Speake to her Hamlet + + Ham. How is it with you Lady? + Qu. Alas, how is't with you? +That you bend your eye on vacancie, +And with their corporall ayre do hold discourse. +Forth at your eyes, your spirits wildely peepe, +And as the sleeping Soldiours in th' Alarme, +Your bedded haire, like life in excrements, +Start vp, and stand an end. Oh gentle Sonne, +Vpon the heate and flame of thy distemper +Sprinkle coole patience. Whereon do you looke? + Ham. On him, on him: look you how pale he glares, +His forme and cause conioyn'd, preaching to stones, +Would make them capeable. Do not looke vpon me, +Least with this pitteous action you conuert +My sterne effects: then what I haue to do, +Will want true colour; teares perchance for blood + + Qu. To who do you speake this? + Ham. Do you see nothing there? + Qu. Nothing at all, yet all that is I see + + Ham. Nor did you nothing heare? + Qu. No, nothing but our selues + + Ham. Why look you there: looke how it steals away: +My Father in his habite, as he liued, +Looke where he goes euen now out at the Portall. +Enter. + + Qu. This is the very coynage of your Braine, +This bodilesse Creation extasie is very cunning in + + Ham. Extasie? +My Pulse as yours doth temperately keepe time, +And makes as healthfull Musicke. It is not madnesse +That I haue vttered; bring me to the Test +And I the matter will re-word: which madnesse +Would gamboll from. Mother, for loue of Grace, +Lay not a flattering Vnction to your soule, +That not your trespasse, but my madnesse speakes: +It will but skin and filme the Vlcerous place, +Whil'st ranke Corruption mining all within, +Infects vnseene. Confesse your selfe to Heauen, +Repent what's past, auoyd what is to come, +And do not spred the Compost on the Weedes, +To make them ranke. Forgiue me this my Vertue, +For in the fatnesse of this pursie times, +Vertue it selfe, of Vice must pardon begge, +Yea courb, and woe, for leaue to do him good + + Qu. Oh Hamlet, +Thou hast cleft my heart in twaine + + Ham. O throw away the worser part of it, +And liue the purer with the other halfe. +Good night, but go not to mine Vnkles bed, +Assume a Vertue, if you haue it not, refraine to night, +And that shall lend a kinde of easinesse +To the next abstinence. Once more goodnight, +And when you are desirous to be blest, +Ile blessing begge of you. For this same Lord, +I do repent: but heauen hath pleas'd it so, +To punish me with this, and this with me, +That I must be their Scourge and Minister. +I will bestow him, and will answer well +The death I gaue him: so againe, good night. +I must be cruell, onely to be kinde; +Thus bad begins and worse remaines behinde + + Qu. What shall I do? + Ham. Not this by no meanes that I bid you do: +Let the blunt King tempt you againe to bed, +Pinch Wanton on your cheeke, call you his Mouse, +And let him for a paire of reechie kisses, +Or padling in your necke with his damn'd Fingers, +Make you to rauell all this matter out, +That I essentially am not in madnesse, +But made in craft. 'Twere good you let him know, +For who that's but a Queene, faire, sober, wise, +Would from a Paddocke, from a Bat, a Gibbe, +Such deere concernings hide, Who would do so, +No in despight of Sense and Secrecie, +Vnpegge the Basket on the houses top: +Let the Birds flye, and like the famous Ape +To try Conclusions in the Basket, creepe +And breake your owne necke downe + + Qu. Be thou assur'd, if words be made of breath, +And breath of life: I haue no life to breath +What thou hast saide to me + + Ham. I must to England, you know that? + Qu. Alacke I had forgot: 'Tis so concluded on + + Ham. This man shall set me packing: +Ile lugge the Guts into the Neighbor roome, +Mother goodnight. Indeede this Counsellor +Is now most still, most secret, and most graue, +Who was in life, a foolish prating Knaue. +Come sir, to draw toward an end with you. +Good night Mother. +Exit Hamlet tugging in Polonius. + +Enter King. + + King. There's matters in these sighes. +These profound heaues +You must translate; Tis fit we vnderstand them. +Where is your Sonne? + Qu. Ah my good Lord, what haue I seene to night? + King. What Gertrude? How do's Hamlet? + Qu. Mad as the Seas, and winde, when both contend +Which is the Mightier, in his lawlesse fit +Behinde the Arras, hearing something stirre, +He whips his Rapier out, and cries a Rat, a Rat, +And in his brainish apprehension killes +The vnseene good old man + + King. Oh heauy deed: +It had bin so with vs had we beene there: +His Liberty is full of threats to all, +To you your selfe, to vs, to euery one. +Alas, how shall this bloody deede be answered? +It will be laide to vs, whose prouidence +Should haue kept short, restrain'd, and out of haunt, +This mad yong man. But so much was our loue, +We would not vnderstand what was most fit, +But like the Owner of a foule disease, +To keepe it from divulging, let's it feede +Euen on the pith of life. Where is he gone? + Qu. To draw apart the body he hath kild, +O're whom his very madnesse like some Oare +Among a Minerall of Mettels base +Shewes it selfe pure. He weepes for what is done + + King. Oh Gertrude, come away: +The Sun no sooner shall the Mountaines touch, +But we will ship him hence, and this vilde deed, +We must with all our Maiesty and Skill +Both countenance, and excuse. +Enter Ros. & Guild. + +Ho Guildenstern: +Friends both go ioyne you with some further ayde: +Hamlet in madnesse hath Polonius slaine, +And from his Mother Clossets hath he drag'd him. +Go seeke him out, speake faire, and bring the body +Into the Chappell. I pray you hast in this. +Exit Gent. + +Come Gertrude, wee'l call vp our wisest friends, +To let them know both what we meane to do, +And what's vntimely done. Oh come away, +My soule is full of discord and dismay. + +Exeunt. + +Enter Hamlet. + + Ham. Safely stowed + + Gentlemen within. Hamlet, Lord Hamlet + + Ham. What noise? Who cals on Hamlet? +Oh heere they come. +Enter Ros. and Guildensterne. + + Ro. What haue you done my Lord with the dead body? + Ham. Compounded it with dust, whereto 'tis Kinne + + Rosin. Tell vs where 'tis, that we may take it thence, +And beare it to the Chappell + + Ham. Do not beleeue it + + Rosin. Beleeue what? + Ham. That I can keepe your counsell, and not mine +owne. Besides, to be demanded of a Spundge, what replication +should be made by the Sonne of a King + + Rosin. Take you me for a Spundge, my Lord? + Ham. I sir, that sokes vp the Kings Countenance, his +Rewards, his Authorities (but such Officers do the King +best seruice in the end. He keepes them like an Ape in +the corner of his iaw, first mouth'd to be last swallowed, +when he needes what you haue glean'd, it is but squeezing +you, and Spundge you shall be dry againe + + Rosin. I vnderstand you not my Lord + + Ham. I am glad of it: a knauish speech sleepes in a +foolish eare + + Rosin. My Lord, you must tell vs where the body is, +and go with vs to the King + + Ham. The body is with the King, but the King is not +with the body. The King, is a thing- + Guild. A thing my Lord? + Ham. Of nothing: bring me to him, hide Fox, and all +after. + +Exeunt. + +Enter King. + + King. I haue sent to seeke him, and to find the bodie: +How dangerous is it that this man goes loose: +Yet must not we put the strong Law on him: +Hee's loued of the distracted multitude, +Who like not in their iudgement, but their eyes: +And where 'tis so, th' Offenders scourge is weigh'd +But neerer the offence: to beare all smooth, and euen, +This sodaine sending him away, must seeme +Deliberate pause, diseases desperate growne, +By desperate appliance are releeued, +Or not at all. +Enter Rosincrane. + +How now? What hath befalne? + Rosin. Where the dead body is bestow'd my Lord, +We cannot get from him + + King. But where is he? + Rosin. Without my Lord, guarded to know your +pleasure + + King. Bring him before vs + + Rosin. Hoa, Guildensterne? Bring in my Lord. +Enter Hamlet and Guildensterne. + + King. Now Hamlet, where's Polonius? + Ham. At Supper + + King. At Supper? Where? + Ham. Not where he eats, but where he is eaten, a certaine +conuocation of wormes are e'ne at him. Your worm +is your onely Emperor for diet. We fat all creatures else +to fat vs, and we fat our selfe for Magots. Your fat King, +and your leane Begger is but variable seruice to dishes, +but to one Table that's the end + + King. What dost thou meane by this? + Ham. Nothing but to shew you how a King may go +a Progresse through the guts of a Begger + + King. Where is Polonius + + Ham. In heauen, send thither to see. If your Messenger +finde him not there, seeke him i'th other place your +selfe: but indeed, if you finde him not this moneth, you +shall nose him as you go vp the staires into the Lobby + + King. Go seeke him there + + Ham. He will stay till ye come + + K. Hamlet, this deed of thine, for thine especial safety +Which we do tender, as we deerely greeue +For that which thou hast done, must send thee hence +With fierie Quicknesse. Therefore prepare thy selfe, +The Barke is readie, and the winde at helpe, +Th' Associates tend, and euery thing at bent +For England + + Ham. For England? + King. I Hamlet + + Ham. Good + + King. So is it, if thou knew'st our purposes + + Ham. I see a Cherube that see's him: but come, for +England. Farewell deere Mother + + King. Thy louing Father Hamlet + + Hamlet. My Mother: Father and Mother is man and +wife: man & wife is one flesh, and so my mother. Come, +for England. + +Exit + + King. Follow him at foote, +Tempt him with speed aboord: +Delay it not, Ile haue him hence to night. +Away, for euery thing is Seal'd and done +That else leanes on th' Affaire, pray you make hast. +And England, if my loue thou holdst at ought, +As my great power thereof may giue thee sense, +Since yet thy Cicatrice lookes raw and red +After the Danish Sword, and thy free awe +Payes homage to vs; thou maist not coldly set +Our Soueraigne Processe, which imports at full +By Letters coniuring to that effect +The present death of Hamlet. Do it England, +For like the Hecticke in my blood he rages, +And thou must cure me: Till I know 'tis done, +How ere my happes, my ioyes were ne're begun. + +Exit + +Enter Fortinbras with an Armie. + + For. Go Captaine, from me greet the Danish King, +Tell him that by his license, Fortinbras +Claimes the conueyance of a promis'd March +Ouer his Kingdome. You know the Rendeuous: +If that his Maiesty would ought with vs, +We shall expresse our dutie in his eye, +And let him know so + + Cap. I will doo't, my Lord + + For. Go safely on. +Enter. + +Enter Queene and Horatio. + + Qu. I will not speake with her + + Hor. She is importunate, indeed distract, her moode +will needs be pittied + + Qu. What would she haue? + Hor. She speakes much of her Father; saies she heares +There's trickes i'th' world, and hems, and beats her heart, +Spurnes enuiously at Strawes, speakes things in doubt, +That carry but halfe sense: Her speech is nothing, +Yet the vnshaped vse of it doth moue +The hearers to Collection; they ayme at it, +And botch the words vp fit to their owne thoughts, +Which as her winkes, and nods, and gestures yeeld them, +Indeed would make one thinke there would be thought, +Though nothing sure, yet much vnhappily + + Qu. 'Twere good she were spoken with, +For she may strew dangerous coniectures +In ill breeding minds. Let her come in. +To my sicke soule (as sinnes true Nature is) +Each toy seemes Prologue, to some great amisse, +So full of Artlesse iealousie is guilt, +It spill's it selfe, in fearing to be spilt. +Enter Ophelia distracted. + + Ophe. Where is the beauteous Maiesty of Denmark + + Qu. How now Ophelia? + Ophe. How should I your true loue know from another one? +By his Cockle hat and staffe, and his Sandal shoone + + Qu. Alas sweet Lady: what imports this Song? + Ophe. Say you? Nay pray you marke. +He is dead and gone Lady, he is dead and gone, +At his head a grasse-greene Turfe, at his heeles a stone. +Enter King. + + Qu. Nay but Ophelia + + Ophe. Pray you marke. +White his Shrow'd as the Mountaine Snow + + Qu. Alas, looke heere my Lord + + Ophe. Larded with sweet Flowers: +Which bewept to the graue did not go, +With true-loue showres + + King. How do ye, pretty Lady? + Ophe. Well, God dil'd you. They say the Owle was +a Bakers daughter. Lord, wee know what we are, but +know not what we may be. God be at your Table + + King. Conceit vpon her Father + + Ophe. Pray you let's haue no words of this: but when +they aske you what it meanes, say you this: +To morrow is S[aint]. Valentines day, all in the morning betime, +And I a Maid at your Window, to be your Valentine. +Then vp he rose, & don'd his clothes, & dupt the chamber dore, +Let in the Maid, that out a Maid, neuer departed more + + King. Pretty Ophelia + + Ophe. Indeed la? without an oath Ile make an end ont. +By gis, and by S[aint]. Charity, +Alacke, and fie for shame: +Yong men wil doo't, if they come too't, +By Cocke they are too blame. +Quoth she before you tumbled me, +You promis'd me to Wed: +So would I ha done by yonder Sunne, +And thou hadst not come to my bed + + King. How long hath she bin thus? + Ophe. I hope all will be well. We must bee patient, +but I cannot choose but weepe, to thinke they should +lay him i'th' cold ground: My brother shall knowe of it, +and so I thanke you for your good counsell. Come, my +Coach: Goodnight Ladies: Goodnight sweet Ladies: +Goodnight, goodnight. +Enter. + + King. Follow her close, +Giue her good watch I pray you: +Oh this is the poyson of deepe greefe, it springs +All from her Fathers death. Oh Gertrude, Gertrude, +When sorrowes comes, they come not single spies, +But in Battalians. First, her Father slaine, +Next your Sonne gone, and he most violent Author +Of his owne iust remoue: the people muddied, +Thicke and vnwholsome in their thoughts, and whispers +For good Polonius death; and we haue done but greenly +In hugger mugger to interre him. Poore Ophelia +Diuided from her selfe, and her faire Iudgement, +Without the which we are Pictures, or meere Beasts. +Last, and as much containing as all these, +Her Brother is in secret come from France, +Keepes on his wonder, keepes himselfe in clouds, +And wants not Buzzers to infect his eare +With pestilent Speeches of his Fathers death, +Where in necessitie of matter Beggard, +Will nothing sticke our persons to Arraigne +In eare and eare. O my deere Gertrude, this, +Like to a murdering Peece in many places, +Giues me superfluous death. + +A Noise within. + +Enter a Messenger. + + Qu. Alacke, what noyse is this? + King. Where are my Switzers? +Let them guard the doore. What is the matter? + Mes. Saue your selfe, my Lord. +The Ocean (ouer-peering of his List) +Eates not the Flats with more impittious haste +Then young Laertes, in a Riotous head, +Ore-beares your Officers, the rabble call him Lord, +And as the world were now but to begin, +Antiquity forgot, Custome not knowne, +The Ratifiers and props of euery word, +They cry choose we? Laertes shall be King, +Caps, hands, and tongues, applaud it to the clouds, +Laertes shall be King, Laertes King + + Qu. How cheerefully on the false Traile they cry, +Oh this is Counter you false Danish Dogges. + +Noise within. Enter Laertes. + + King. The doores are broke + + Laer. Where is the King, sirs? Stand you all without + + All. No, let's come in + + Laer. I pray you giue me leaue + + Al. We will, we will + + Laer. I thanke you: Keepe the doore. +Oh thou vilde King, giue me my Father + + Qu. Calmely good Laertes + + Laer. That drop of blood, that calmes +Proclaimes me Bastard: +Cries Cuckold to my Father, brands the Harlot +Euen heere betweene the chaste vnsmirched brow +Of my true Mother + + King. What is the cause Laertes, +That thy Rebellion lookes so Gyant-like? +Let him go Gertrude: Do not feare our person: +There's such Diuinity doth hedge a King, +That Treason can but peepe to what it would, +Acts little of his will. Tell me Laertes, +Why thou art thus Incenst? Let him go Gertrude. +Speake man + + Laer. Where's my Father? + King. Dead + + Qu. But not by him + + King. Let him demand his fill + + Laer. How came he dead? Ile not be Iuggel'd with. +To hell Allegeance: Vowes, to the blackest diuell. +Conscience and Grace, to the profoundest Pit. +I dare Damnation: to this point I stand, +That both the worlds I giue to negligence, +Let come what comes: onely Ile be reueng'd +Most throughly for my Father + + King. Who shall stay you? + Laer. My Will, not all the world, +And for my meanes, Ile husband them so well, +They shall go farre with little + + King. Good Laertes: +If you desire to know the certaintie +Of your deere Fathers death, if writ in your reuenge, +That Soop-stake you will draw both Friend and Foe, +Winner and Looser + + Laer. None but his Enemies + + King. Will you know them then + + La. To his good Friends, thus wide Ile ope my Armes: +And like the kinde Life-rend'ring Politician, +Repast them with my blood + + King. Why now you speake +Like a good Childe, and a true Gentleman. +That I am guiltlesse of your Fathers death, +And am most sensible in greefe for it, +It shall as leuell to your Iudgement pierce +As day do's to your eye. + +A noise within. Let her come in. + +Enter Ophelia. + + Laer. How now? what noise is that? +Oh heate drie vp my Braines, teares seuen times salt, +Burne out the Sence and Vertue of mine eye. +By Heauen, thy madnesse shall be payed by waight, +Till our Scale turnes the beame. Oh Rose of May, +Deere Maid, kinde Sister, sweet Ophelia: +Oh Heauens, is't possible, a yong Maids wits, +Should be as mortall as an old mans life? +Nature is fine in Loue, and where 'tis fine, +It sends some precious instance of it selfe +After the thing it loues + + Ophe. They bore him bare fac'd on the Beer, +Hey non nony, nony, hey nony: +And on his graue raines many a teare, +Fare you well my Doue + + Laer. Had'st thou thy wits, and did'st perswade Reuenge, +it could not moue thus + + Ophe. You must sing downe a-downe, and you call +him a-downe-a. Oh, how the wheele becomes it? It is +the false Steward that stole his masters daughter + + Laer. This nothings more then matter + + Ophe. There's Rosemary, that's for Remembraunce. +Pray loue remember: and there is Paconcies, that's for +Thoughts + + Laer. A document in madnesse, thoughts & remembrance +fitted + + Ophe. There's Fennell for you, and Columbines: ther's +Rew for you, and heere's some for me. Wee may call it +Herbe-Grace a Sundaies: Oh you must weare your Rew +with a difference. There's a Daysie, I would giue you +some Violets, but they wither'd all when my Father dyed: +They say, he made a good end; +For bonny sweet Robin is all my ioy + + Laer. Thought, and Affliction, Passion, Hell it selfe: +She turnes to Fauour, and to prettinesse + + Ophe. And will he not come againe, +And will he not come againe: +No, no, he is dead, go to thy Death-bed, +He neuer wil come againe. +His Beard as white as Snow, +All Flaxen was his Pole: +He is gone, he is gone, and we cast away mone, +Gramercy on his Soule. +And of all Christian Soules, I pray God. +God buy ye. + +Exeunt. Ophelia + + Laer. Do you see this, you Gods? + King. Laertes, I must common with your greefe, +Or you deny me right: go but apart, +Make choice of whom your wisest Friends you will, +And they shall heare and iudge 'twixt you and me; +If by direct or by Colaterall hand +They finde vs touch'd, we will our Kingdome giue, +Our Crowne, our Life, and all that we call Ours +To you in satisfaction. But if not, +Be you content to lend your patience to vs, +And we shall ioyntly labour with your soule +To giue it due content + + Laer. Let this be so: +His meanes of death, his obscure buriall; +No Trophee, Sword, nor Hatchment o're his bones, +No Noble rite, nor formall ostentation, +Cry to be heard, as 'twere from Heauen to Earth, +That I must call in question + + King. So you shall: +And where th' offence is, let the great Axe fall. +I pray you go with me. + +Exeunt. + +Enter Horatio, with an Attendant. + + Hora. What are they that would speake with me? + Ser. Saylors sir, they say they haue Letters for you + + Hor. Let them come in, +I do not know from what part of the world +I should be greeted, if not from Lord Hamlet. +Enter Saylor. + + Say. God blesse you Sir + + Hor. Let him blesse thee too + + Say. Hee shall Sir, and't please him. There's a Letter +for you Sir: It comes from th' Ambassadours that was +bound for England, if your name be Horatio, as I am let +to know it is. + +Reads the Letter. + +Horatio, When thou shalt haue ouerlook'd this, giue these +Fellowes some meanes to the King: They haue Letters +for him. Ere we were two dayes old at Sea, a Pyrate of very +Warlicke appointment gaue vs Chace. Finding our selues too +slow of Saile, we put on a compelled Valour. In the Grapple, I +boorded them: On the instant they got cleare of our Shippe, so +I alone became their Prisoner. They haue dealt with mee, like +Theeues of Mercy, but they knew what they did. I am to doe +a good turne for them. Let the King haue the Letters I haue +sent, and repaire thou to me with as much hast as thou wouldest +flye death. I haue words to speake in your eare, will make thee +dumbe, yet are they much too light for the bore of the Matter. +These good Fellowes will bring thee where I am. Rosincrance +and Guildensterne, hold their course for England. Of them +I haue much to tell thee, Farewell. +He that thou knowest thine, +Hamlet. +Come, I will giue you way for these your Letters, +And do't the speedier, that you may direct me +To him from whom you brought them. +Enter. + +Enter King and Laertes. + + King. Now must your conscience my acquittance seal, +And you must put me in your heart for Friend, +Sith you haue heard, and with a knowing eare, +That he which hath your Noble Father slaine, +Pursued my life + + Laer. It well appeares. But tell me, +Why you proceeded not against these feates, +So crimefull, and so Capitall in Nature, +As by your Safety, Wisedome, all things else, +You mainly were stirr'd vp? + King. O for two speciall Reasons, +Which may to you (perhaps) seeme much vnsinnowed, +And yet to me they are strong. The Queen his Mother, +Liues almost by his lookes: and for my selfe, +My Vertue or my Plague, be it either which, +She's so coniunctiue to my life, and soule; +That as the Starre moues not but in his Sphere, +I could not but by her. The other Motiue, +Why to a publike count I might not go, +Is the great loue the generall gender beare him, +Who dipping all his Faults in their affection, +Would like the Spring that turneth Wood to Stone, +Conuert his Gyues to Graces. So that my Arrowes +Too slightly timbred for so loud a Winde, +Would haue reuerted to my Bow againe, +And not where I had arm'd them + + Laer. And so haue I a Noble Father lost, +A Sister driuen into desperate tearmes, +Who was (if praises may go backe againe) +Stood Challenger on mount of all the Age +For her perfections. But my reuenge will come + + King. Breake not your sleepes for that, +You must not thinke +That we are made of stuffe, so flat, and dull, +That we can let our Beard be shooke with danger, +And thinke it pastime. You shortly shall heare more, +I lou'd your Father, and we loue our Selfe, +And that I hope will teach you to imagine- +Enter a Messenger. + +How now? What Newes? + Mes. Letters my Lord from Hamlet, This to your +Maiesty: this to the Queene + + King. From Hamlet? Who brought them? + Mes. Saylors my Lord they say, I saw them not: +They were giuen me by Claudio, he receiu'd them + + King. Laertes you shall heare them: +Leaue vs. + +Exit Messenger + +High and Mighty, you shall know I am set naked on your +Kingdome. To morrow shall I begge leaue to see your Kingly +Eyes. When I shall (first asking your Pardon thereunto) recount +th' Occasions of my sodaine, and more strange returne. +Hamlet. +What should this meane? Are all the rest come backe? +Or is it some abuse? Or no such thing? + Laer. Know you the hand? + Kin. 'Tis Hamlets Character, naked and in a Postscript +here he sayes alone: Can you aduise me? + Laer. I'm lost in it my Lord; but let him come, +It warmes the very sicknesse in my heart, +That I shall liue and tell him to his teeth; +Thus diddest thou + + Kin. If it be so Laertes, as how should it be so: +How otherwise will you be rul'd by me? + Laer. If so you'l not o'rerule me to a peace + + Kin. To thine owne peace: if he be now return'd, +As checking at his Voyage, and that he meanes +No more to vndertake it; I will worke him +To an exployt now ripe in my Deuice, +Vnder the which he shall not choose but fall; +And for his death no winde of blame shall breath, +But euen his Mother shall vncharge the practice, +And call it accident: Some two Monthes hence +Here was a Gentleman of Normandy, +I'ue seene my selfe, and seru'd against the French, +And they ran well on Horsebacke; but this Gallant +Had witchcraft in't; he grew into his Seat, +And to such wondrous doing brought his Horse, +As had he beene encorps't and demy-Natur'd +With the braue Beast, so farre he past my thought, +That I in forgery of shapes and trickes, +Come short of what he did + + Laer. A Norman was't? + Kin. A Norman + + Laer. Vpon my life Lamound + + Kin. The very same + + Laer. I know him well, he is the Brooch indeed, +And Iemme of all our Nation + + Kin. Hee mad confession of you, +And gaue you such a Masterly report, +For Art and exercise in your defence; +And for your Rapier most especiall, +That he cryed out, t'would be a sight indeed, +If one could match you Sir. This report of his +Did Hamlet so envenom with his Enuy, +That he could nothing doe but wish and begge, +Your sodaine comming ore to play with him; +Now out of this + + Laer. Why out of this, my Lord? + Kin. Laertes was your Father deare to you? +Or are you like the painting of a sorrow, +A face without a heart? + Laer. Why aske you this? + Kin. Not that I thinke you did not loue your Father, +But that I know Loue is begun by Time: +And that I see in passages of proofe, +Time qualifies the sparke and fire of it: +Hamlet comes backe: what would you vndertake, +To show your selfe your Fathers sonne indeed, +More then in words? + Laer. To cut his throat i'th' Church + + Kin. No place indeed should murder Sancturize; +Reuenge should haue no bounds: but good Laertes +Will you doe this, keepe close within your Chamber, +Hamlet return'd, shall know you are come home: +Wee'l put on those shall praise your excellence, +And set a double varnish on the fame +The Frenchman gaue you, bring you in fine together, +And wager on your heads, he being remisse, +Most generous, and free from all contriuing, +Will not peruse the Foiles? So that with ease, +Or with a little shuffling, you may choose +A Sword vnbaited, and in a passe of practice, +Requit him for your Father + + Laer. I will doo't. +And for that purpose Ile annoint my Sword: +I bought an Vnction of a Mountebanke +So mortall, I but dipt a knife in it, +Where it drawes blood, no Cataplasme so rare, +Collected from all Simples that haue Vertue +Vnder the Moone, can saue the thing from death, +That is but scratcht withall: Ile touch my point, +With this contagion, that if I gall him slightly, +It may be death + + Kin. Let's further thinke of this, +Weigh what conuenience both of time and meanes +May fit vs to our shape, if this should faile; +And that our drift looke through our bad performance, +'Twere better not assaid; therefore this Proiect +Should haue a backe or second, that might hold, +If this should blast in proofe: Soft, let me see +Wee'l make a solemne wager on your commings, +I ha't: when in your motion you are hot and dry, +As make your bowts more violent to the end, +And that he cals for drinke; Ile haue prepar'd him +A Challice for the nonce; whereon but sipping, +If he by chance escape your venom'd stuck, +Our purpose may hold there; how sweet Queene. +Enter Queene. + + Queen. One woe doth tread vpon anothers heele, +So fast they'l follow: your Sister's drown'd Laertes + + Laer. Drown'd! O where? + Queen. There is a Willow growes aslant a Brooke, +That shewes his hore leaues in the glassie streame: +There with fantasticke Garlands did she come, +Of Crow-flowers, Nettles, Daysies, and long Purples, +That liberall Shepheards giue a grosser name; +But our cold Maids doe Dead Mens Fingers call them: +There on the pendant boughes, her Coronet weeds +Clambring to hang; an enuious sliuer broke, +When downe the weedy Trophies, and her selfe, +Fell in the weeping Brooke, her cloathes spred wide, +And Mermaid-like, a while they bore her vp, +Which time she chaunted snatches of old tunes, +As one incapable of her owne distresse, +Or like a creature Natiue, and indued +Vnto that Element: but long it could not be, +Till that her garments, heauy with her drinke, +Pul'd the poore wretch from her melodious buy, +To muddy death + + Laer. Alas then, is she drown'd? + Queen. Drown'd, drown'd + + Laer. Too much of water hast thou poore Ophelia, +And therefore I forbid my teares: but yet +It is our tricke, Nature her custome holds, +Let shame say what it will; when these are gone +The woman will be out: Adue my Lord, +I haue a speech of fire, that faine would blaze, +But that this folly doubts it. +Enter. + + Kin. Let's follow, Gertrude: +How much I had to doe to calme his rage? +Now feare I this will giue it start againe; +Therefore let's follow. + +Exeunt. + +Enter two Clownes. + + Clown. Is she to bee buried in Christian buriall, that +wilfully seekes her owne saluation? + Other. I tell thee she is, and therefore make her Graue +straight, the Crowner hath sate on her, and finds it Christian +buriall + + Clo. How can that be, vnlesse she drowned her selfe in +her owne defence? + Other. Why 'tis found so + + Clo. It must be Se offendendo, it cannot bee else: for +heere lies the point; If I drowne my selfe wittingly, it argues +an Act: and an Act hath three branches. It is an +Act to doe and to performe; argall she drown'd her selfe +wittingly + + Other. Nay but heare you Goodman Deluer + + Clown. Giue me leaue; heere lies the water; good: +heere stands the man; good: If the man goe to this water +and drowne himselfe; it is will he nill he, he goes; +marke you that? But if the water come to him & drowne +him; hee drownes not himselfe. Argall, hee that is not +guilty of his owne death, shortens not his owne life + + Other. But is this law? + Clo. I marry is't, Crowners Quest Law + + Other. Will you ha the truth on't: if this had not +beene a Gentlewoman, shee should haue beene buried +out of Christian Buriall + + Clo. Why there thou say'st. And the more pitty that +great folke should haue countenance in this world to +drowne or hang themselues, more then their euen Christian. +Come, my Spade; there is no ancient Gentlemen, +but Gardiners, Ditchers and Graue-makers; they hold vp +Adams Profession + + Other. Was he a Gentleman? + Clo. He was the first that euer bore Armes + + Other. Why he had none + + Clo. What, ar't a Heathen? how doth thou vnderstand +the Scripture? the Scripture sayes Adam dig'd; +could hee digge without Armes? Ile put another question +to thee; if thou answerest me not to the purpose, confesse +thy selfe- + Other. Go too + + Clo. What is he that builds stronger then either the +Mason, the Shipwright, or the Carpenter? + Other. The Gallowes maker; for that Frame outliues a +thousand Tenants + + Clo. I like thy wit well in good faith, the Gallowes +does well; but how does it well? it does well to those +that doe ill: now, thou dost ill to say the Gallowes is +built stronger then the Church: Argall, the Gallowes +may doe well to thee. Too't againe, Come + + Other. Who builds stronger then a Mason, a Shipwright, +or a Carpenter? + Clo. I, tell me that, and vnyoake + + Other. Marry, now I can tell + + Clo. Too't + + Other. Masse, I cannot tell. +Enter Hamlet and Horatio a farre off. + + Clo. Cudgell thy braines no more about it; for your +dull Asse will not mend his pace with beating; and when +you are ask't this question next, say a Graue-maker: the +Houses that he makes, lasts till Doomesday: go, get thee +to Yaughan, fetch me a stoupe of Liquor. + +Sings. + +In youth when I did loue, did loue, +me thought it was very sweete: +To contract O the time for a my behoue, +O me thought there was nothing meete + + Ham. Ha's this fellow no feeling of his businesse, that +he sings at Graue-making? + Hor. Custome hath made it in him a property of easinesse + + Ham. 'Tis ee'n so; the hand of little Imployment hath +the daintier sense + + Clowne sings. But Age with his stealing steps +hath caught me in his clutch: +And hath shipped me intill the Land, +as if I had neuer beene such + + Ham. That Scull had a tongue in it, and could sing +once: how the knaue iowles it to th' grownd, as if it +were Caines Iaw-bone, that did the first murther: It +might be the Pate of a Polititian which this Asse o're Offices: +one that could circumuent God, might it not? + Hor. It might, my Lord + + Ham. Or of a Courtier, which could say, Good Morrow +sweet Lord: how dost thou, good Lord? this +might be my Lord such a one, that prais'd my Lord such +a ones Horse, when he meant to begge it; might it not? + Hor. I, my Lord + + Ham. Why ee'n so: and now my Lady Wormes, +Chaplesse, and knockt about the Mazard with a Sextons +Spade; heere's fine Reuolution, if wee had the tricke to +see't. Did these bones cost no more the breeding, but +to play at Loggets with 'em? mine ake to thinke +on't + + Clowne sings. A Pickhaxe and a Spade, a Spade, +for and a shrowding-Sheete: +O a Pit of Clay for to be made, +for such a Guest is meete + + Ham. There's another: why might not that bee the +Scull of a Lawyer? where be his Quiddits now? his +Quillets? his Cases? his Tenures, and his Tricks? why +doe's he suffer this rude knaue now to knocke him about +the Sconce with a dirty Shouell, and will not tell him of +his Action of Battery? hum. This fellow might be in's +time a great buyer of Land, with his Statutes, his Recognizances, +his Fines, his double Vouchers, his Recoueries: +Is this the fine of his Fines, and the recouery of his Recoueries, +to haue his fine Pate full of fine Dirt? will his +Vouchers vouch him no more of his Purchases, and double +ones too, then the length and breadth of a paire of +Indentures? the very Conueyances of his Lands will +hardly lye in this Boxe; and must the Inheritor himselfe +haue no more? ha? + Hor. Not a iot more, my Lord + + Ham. Is not Parchment made of Sheep-skinnes? + Hor. I my Lord, and of Calue-skinnes too + + Ham. They are Sheepe and Calues that seek out assurance +in that. I will speake to this fellow: whose Graue's +this Sir? + Clo. Mine Sir: +O a Pit of Clay for to be made, +for such a Guest is meete + + Ham. I thinke it be thine indeed: for thou liest in't + + Clo. You lye out on't Sir, and therefore it is not yours: +for my part, I doe not lye in't; and yet it is mine + + Ham. Thou dost lye in't, to be in't and say 'tis thine: +'tis for the dead, not for the quicke, therefore thou +lyest + + Clo. 'Tis a quicke lye Sir, 'twill away againe from me +to you + + Ham. What man dost thou digge it for? + Clo. For no man Sir + + Ham. What woman then? + Clo. For none neither + + Ham. Who is to be buried in't? + Clo. One that was a woman Sir; but rest her Soule, +shee's dead + + Ham. How absolute the knaue is? wee must speake +by the Carde, or equiuocation will vndoe vs: by the +Lord Horatio, these three yeares I haue taken note of it, +the Age is growne so picked, that the toe of the Pesant +comes so neere the heeles of our Courtier, hee galls his +Kibe. How long hast thou been a Graue-maker? + Clo. Of all the dayes i'th' yeare, I came too't that day +that our last King Hamlet o'recame Fortinbras + + Ham. How long is that since? + Clo. Cannot you tell that? euery foole can tell that: +It was the very day, that young Hamlet was borne, hee +that was mad, and sent into England + + Ham. I marry, why was he sent into England? + Clo. Why, because he was mad; hee shall recouer his +wits there; or if he do not, it's no great matter there + + Ham. Why? + Clo. 'Twill not be seene in him, there the men are as +mad as he + + Ham. How came he mad? + Clo. Very strangely they say + + Ham. How strangely? + Clo. Faith e'ene with loosing his wits + + Ham. Vpon what ground? + Clo. Why heere in Denmarke: I haue bin sixeteene +heere, man and Boy thirty yeares + + Ham. How long will a man lie i'th' earth ere he rot? + Clo. Ifaith, if he be not rotten before he die (as we haue +many pocky Coarses now adaies, that will scarce hold +the laying in) he will last you some eight yeare, or nine +yeare. A Tanner will last you nine yeare + + Ham. Why he, more then another? + Clo. Why sir, his hide is so tan'd with his Trade, that +he will keepe out water a great while. And your water, +is a sore Decayer of your horson dead body. Heres a Scull +now: this Scul, has laine in the earth three & twenty years + + Ham. Whose was it? + Clo. A whoreson mad Fellowes it was; +Whose doe you thinke it was? + Ham. Nay, I know not + + Clo. A pestilence on him for a mad Rogue, a pour'd a +Flaggon of Renish on my head once. This same Scull +Sir, this same Scull sir, was Yoricks Scull, the Kings Iester + + Ham. This? + Clo. E'ene that + + Ham. Let me see. Alas poore Yorick, I knew him Horatio, +a fellow of infinite Iest; of most excellent fancy, he +hath borne me on his backe a thousand times: And how +abhorred my Imagination is, my gorge rises at it. Heere +hung those lipps, that I haue kist I know not how oft. +Where be your Iibes now? Your Gambals? Your +Songs? Your flashes of Merriment that were wont to +set the Table on a Rore? No one now to mock your own +Ieering? Quite chopfalne? Now get you to my Ladies +Chamber, and tell her, let her paint an inch thicke, to this +fauour she must come. Make her laugh at that: prythee +Horatio tell me one thing + + Hor. What's that my Lord? + Ham. Dost thou thinke Alexander lookt o'this fashion +i'th' earth? + Hor. E'ene so + + Ham. And smelt so? Puh + + Hor. E'ene so, my Lord + + Ham. To what base vses we may returne Horatio. +Why may not Imagination trace the Noble dust of Alexander, +till he find it stopping a bunghole + + Hor. 'Twere to consider: to curiously to consider so + + Ham. No faith, not a iot. But to follow him thether +with modestie enough, & likeliehood to lead it; as thus. +Alexander died: Alexander was buried: Alexander returneth +into dust; the dust is earth; of earth we make +Lome, and why of that Lome (whereto he was conuerted) +might they not stopp a Beere-barrell? +Imperiall Caesar, dead and turn'd to clay, +Might stop a hole to keepe the winde away. +Oh, that that earth, which kept the world in awe, +Should patch a Wall, t' expell the winters flaw. +But soft, but soft, aside; heere comes the King. +Enter King, Queene, Laertes, and a Coffin, with Lords attendant. + +The Queene, the Courtiers. Who is that they follow, +And with such maimed rites? This doth betoken, +The Coarse they follow, did with disperate hand, +Fore do it owne life; 'twas some Estate. +Couch we a while, and mark + + Laer. What Cerimony else? + Ham. That is Laertes, a very Noble youth: Marke + + Laer. What Cerimony else? + Priest. Her Obsequies haue bin as farre inlarg'd. +As we haue warrantie, her death was doubtfull, +And but that great Command, o're-swaies the order, +She should in ground vnsanctified haue lodg'd, +Till the last Trumpet. For charitable praier, +Shardes, Flints, and Peebles, should be throwne on her: +Yet heere she is allowed her Virgin Rites, +Her Maiden strewments, and the bringing home +Of Bell and Buriall + + Laer. Must there no more be done ? + Priest. No more be done: +We should prophane the seruice of the dead, +To sing sage Requiem, and such rest to her +As to peace-parted Soules + + Laer. Lay her i'th' earth, +And from her faire and vnpolluted flesh, +May Violets spring. I tell thee (churlish Priest) +A Ministring Angell shall my Sister be, +When thou liest howling? + Ham. What, the faire Ophelia? + Queene. Sweets, to the sweet farewell. +I hop'd thou should'st haue bin my Hamlets wife: +I thought thy Bride-bed to haue deckt (sweet Maid) +And not t'haue strew'd thy Graue + + Laer. Oh terrible woer, +Fall ten times trebble, on that cursed head +Whose wicked deed, thy most Ingenious sence +Depriu'd thee of. Hold off the earth a while, +Till I haue caught her once more in mine armes: + +Leaps in the graue. + +Now pile your dust, vpon the quicke, and dead, +Till of this flat a Mountaine you haue made, +To o're top old Pelion, or the skyish head +Of blew Olympus + + Ham. What is he, whose griefes +Beares such an Emphasis? whose phrase of Sorrow +Coniure the wandring Starres, and makes them stand +Like wonder-wounded hearers? This is I, +Hamlet the Dane + + Laer. The deuill take thy soule + + Ham. Thou prai'st not well, +I prythee take thy fingers from my throat; +Sir though I am not Spleenatiue, and rash, +Yet haue I something in me dangerous, +Which let thy wisenesse feare. Away thy hand + + King. Pluck them asunder + + Qu. Hamlet, Hamlet + + Gen. Good my Lord be quiet + + Ham. Why I will fight with him vppon this Theme. +Vntill my eielids will no longer wag + + Qu. Oh my Sonne, what Theame? + Ham. I lou'd Ophelia; fortie thousand Brothers +Could not (with all there quantitie of Loue) +Make vp my summe. What wilt thou do for her? + King. Oh he is mad Laertes, + Qu. For loue of God forbeare him + + Ham. Come show me what thou'lt doe. +Woo't weepe? Woo't fight? Woo't teare thy selfe? +Woo't drinke vp Esile, eate a Crocodile? +Ile doo't. Dost thou come heere to whine; +To outface me with leaping in her Graue? +Be buried quicke with her, and so will I. +And if thou prate of Mountaines; let them throw +Millions of Akers on vs; till our ground +Sindging his pate against the burning Zone, +Make Ossa like a wart. Nay, and thou'lt mouth, +Ile rant as well as thou + + Kin. This is meere Madnesse: +And thus awhile the fit will worke on him: +Anon as patient as the female Doue, +When that her Golden Cuplet are disclos'd; +His silence will sit drooping + + Ham. Heare you Sir: +What is the reason that you vse me thus? +I lou'd you euer; but it is no matter: +Let Hercules himselfe doe what he may, +The Cat will Mew, and Dogge will haue his day. +Enter. + + Kin. I pray you good Horatio wait vpon him, +Strengthen your patience in our last nights speech, +Wee'l put the matter to the present push: +Good Gertrude set some watch ouer your Sonne, +This Graue shall haue a liuing Monument: +An houre of quiet shortly shall we see; +Till then, in patience our proceeding be. + +Exeunt. + +Enter Hamlet and Horatio + + Ham. So much for this Sir; now let me see the other, +You doe remember all the Circumstance + + Hor. Remember it my Lord? + Ham. Sir, in my heart there was a kinde of fighting, +That would not let me sleepe; me thought I lay +Worse then the mutines in the Bilboes, rashly, +(And praise be rashnesse for it) let vs know, +Our indiscretion sometimes serues vs well, +When our deare plots do paule, and that should teach vs, +There's a Diuinity that shapes our ends, +Rough-hew them how we will + + Hor. That is most certaine + + Ham. Vp from my Cabin +My sea-gowne scarft about me in the darke, +Grop'd I to finde out them; had my desire, +Finger'd their Packet, and in fine, withdrew +To mine owne roome againe, making so bold, +(My feares forgetting manners) to vnseale +Their grand Commission, where I found Horatio, +Oh royall knauery: An exact command, +Larded with many seuerall sorts of reason; +Importing Denmarks health, and Englands too, +With hoo, such Bugges and Goblins in my life, +That on the superuize no leasure bated, +No not to stay the grinding of the Axe, +My head should be struck off + + Hor. Ist possible? + Ham. Here's the Commission, read it at more leysure: +But wilt thou heare me how I did proceed? + Hor. I beseech you + + Ham. Being thus benetted round with Villaines, +Ere I could make a Prologue to my braines, +They had begun the Play. I sate me downe, +Deuis'd a new Commission, wrote it faire, +I once did hold it as our Statists doe, +A basenesse to write faire; and laboured much +How to forget that learning: but Sir now, +It did me Yeomans seriuce: wilt thou know +The effects of what I wrote? + Hor. I, good my Lord + + Ham. An earnest Coniuration from the King, +As England was his faithfull Tributary, +As loue betweene them, as the Palme should flourish, +As Peace should still her wheaten Garland weare, +And stand a Comma 'tweene their amities, +And many such like Assis of great charge, +That on the view and know of these Contents, +Without debatement further, more or lesse, +He should the bearers put to sodaine death, +Not shriuing time allowed + + Hor. How was this seal'd? + Ham. Why, euen in that was Heauen ordinate; +I had my fathers Signet in my Purse, +Which was the Modell of that Danish Seale: +Folded the Writ vp in forme of the other, +Subscrib'd it, gau't th' impression, plac't it safely, +The changeling neuer knowne: Now, the next day +Was our Sea Fight, and what to this was sement, +Thou know'st already + + Hor. So Guildensterne and Rosincrance, go too't + + Ham. Why man, they did make loue to this imployment +They are not neere my Conscience; their debate +Doth by their owne insinuation grow: +'Tis dangerous, when the baser nature comes +Betweene the passe, and fell incensed points +Of mighty opposites + + Hor. Why, what a King is this? + Ham. Does it not, thinkst thee, stand me now vpon +He that hath kil'd my King, and whor'd my Mother, +Popt in betweene th' election and my hopes, +Throwne out his Angle for my proper life, +And with such coozenage; is't not perfect conscience, +To quit him with this arme? And is't not to be damn'd +To let this Canker of our nature come +In further euill + + Hor. It must be shortly knowne to him from England +What is the issue of the businesse there + + Ham. It will be short, +The interim's mine, and a mans life's no more +Then to say one: but I am very sorry good Horatio, +That to Laertes I forgot my selfe; +For by the image of my Cause, I see +The Portraiture of his; Ile count his fauours: +But sure the brauery of his griefe did put me +Into a Towring passion + + Hor. Peace, who comes heere? +Enter young Osricke. + + Osr. Your Lordship is right welcome back to Denmarke + + Ham. I humbly thank you Sir, dost know this waterflie? + Hor. No my good Lord + + Ham. Thy state is the more gracious; for 'tis a vice to +know him: he hath much Land, and fertile; let a Beast +be Lord of Beasts, and his Crib shall stand at the Kings +Messe; 'tis a Chowgh; but as I saw spacious in the possession +of dirt + + Osr. Sweet Lord, if your friendship were at leysure, +I should impart a thing to you from his Maiesty + + Ham. I will receiue it with all diligence of spirit; put +your Bonet to his right vse, 'tis for the head + + Osr. I thanke your Lordship, 'tis very hot + + Ham. No, beleeue mee 'tis very cold, the winde is +Northerly + + Osr. It is indifferent cold my Lord indeed + + Ham. Mee thinkes it is very soultry, and hot for my +Complexion + + Osr. Exceedingly, my Lord, it is very soultry, as 'twere +I cannot tell how: but my Lord, his Maiesty bad me signifie +to you, that he ha's laid a great wager on your head: +Sir, this is the matter + + Ham. I beseech you remember + + Osr. Nay, in good faith, for mine ease in good faith: +Sir, you are not ignorant of what excellence Laertes is at +his weapon + + Ham. What's his weapon? + Osr. Rapier and dagger + + Ham. That's two of his weapons; but well + + Osr. The sir King ha's wag'd with him six Barbary horses, +against the which he impon'd as I take it, sixe French +Rapiers and Poniards, with their assignes, as Girdle, +Hangers or so: three of the Carriages infaith are very +deare to fancy, very responsiue to the hilts, most delicate +carriages, and of very liberall conceit + + Ham. What call you the Carriages? + Osr. The Carriages Sir, are the hangers + + Ham. The phrase would bee more Germaine to the +matter: If we could carry Cannon by our sides; I would +it might be Hangers till then; but on sixe Barbary Horses +against sixe French Swords: their Assignes, and three +liberall conceited Carriages, that's the French but against +the Danish; why is this impon'd as you call it? + Osr. The King Sir, hath laid that in a dozen passes betweene +you and him, hee shall not exceed you three hits; +He hath one twelue for mine, and that would come to +imediate tryall, if your Lordship would vouchsafe the +Answere + + Ham. How if I answere no? + Osr. I meane my Lord, the opposition of your person +in tryall + + Ham. Sir, I will walke heere in the Hall; if it please +his Maiestie, 'tis the breathing time of day with me; let +the Foyles bee brought, the Gentleman willing, and the +King hold his purpose; I will win for him if I can: if +not, Ile gaine nothing but my shame, and the odde hits + + Osr. Shall I redeliuer you ee'n so? + Ham. To this effect Sir, after what flourish your nature +will + + Osr. I commend my duty to your Lordship + + Ham. Yours, yours; hee does well to commend it +himselfe, there are no tongues else for's tongue + + Hor. This Lapwing runs away with the shell on his +head + + Ham. He did Complie with his Dugge before hee +suck't it: thus had he and mine more of the same Beauty +that I know the drossie age dotes on; only got the tune of +the time, and outward habite of encounter, a kinde of +yesty collection, which carries them through & through +the most fond and winnowed opinions; and doe but blow +them to their tryalls: the Bubbles are out + + Hor. You will lose this wager, my Lord + + Ham. I doe not thinke so, since he went into France, +I haue beene in continuall practice; I shall winne at the +oddes: but thou wouldest not thinke how all heere about +my heart: but it is no matter + + Hor. Nay, good my Lord + + Ham. It is but foolery; but it is such a kinde of +gain-giuing as would perhaps trouble a woman + + Hor. If your minde dislike any thing, obey. I will forestall +their repaire hither, and say you are not fit + + Ham. Not a whit, we defie Augury; there's a speciall +Prouidence in the fall of a sparrow. If it be now, 'tis not +to come: if it bee not to come, it will bee now: if it +be not now; yet it will come; the readinesse is all, since no +man ha's ought of what he leaues. What is't to leaue betimes? +Enter King, Queene, Laertes and Lords, with other Attendants with +Foyles, +and Gauntlets, a Table and Flagons of Wine on it. + + Kin. Come Hamlet, come, and take this hand from me + + Ham. Giue me your pardon Sir, I'ue done you wrong, +But pardon't as you are a Gentleman. +This presence knowes, +And you must needs haue heard how I am punisht +With sore distraction? What I haue done +That might your nature honour, and exception +Roughly awake, I heere proclaime was madnesse: +Was't Hamlet wrong'd Laertes? Neuer Hamlet. +If Hamlet from himselfe be tane away: +And when he's not himselfe, do's wrong Laertes, +Then Hamlet does it not, Hamlet denies it: +Who does it then? His Madnesse? If't be so, +Hamlet is of the Faction that is wrong'd, +His madnesse is poore Hamlets Enemy. +Sir, in this Audience, +Let my disclaiming from a purpos'd euill, +Free me so farre in your most generous thoughts, +That I haue shot mine Arrow o're the house, +And hurt my Mother + + Laer. I am satisfied in Nature, +Whose motiue in this case should stirre me most +To my Reuenge. But in my termes of Honor +I stand aloofe, and will no reconcilement, +Till by some elder Masters of knowne Honor, +I haue a voyce, and president of peace +To keepe my name vngorg'd. But till that time, +I do receiue your offer'd loue like loue, +And wil not wrong it + + Ham. I do embrace it freely, +And will this Brothers wager frankely play. +Giue vs the Foyles: Come on + + Laer. Come one for me + + Ham. Ile be your foile Laertes, in mine ignorance, +Your Skill shall like a Starre i'th' darkest night, +Sticke fiery off indeede + + Laer. You mocke me Sir + + Ham. No by this hand + + King. Giue them the Foyles yong Osricke, +Cousen Hamlet, you know the wager + + Ham. Verie well my Lord, +Your Grace hath laide the oddes a'th' weaker side + + King. I do not feare it, +I haue seene you both: +But since he is better'd, we haue therefore oddes + + Laer. This is too heauy, +Let me see another + + Ham. This likes me well, +These Foyles haue all a length. + +Prepare to play. + + Osricke. I my good Lord + + King. Set me the Stopes of wine vpon that Table: +If Hamlet giue the first, or second hit, +Or quit in answer of the third exchange, +Let all the Battlements their Ordinance fire, +The King shal drinke to Hamlets better breath, +And in the Cup an vnion shal he throw +Richer then that, which foure successiue Kings +In Denmarkes Crowne haue worne. +Giue me the Cups, +And let the Kettle to the Trumpets speake, +The Trumpet to the Cannoneer without, +The Cannons to the Heauens, the Heauen to Earth, +Now the King drinkes to Hamlet. Come, begin, +And you the Iudges beare a wary eye + + Ham. Come on sir + + Laer. Come on sir. + +They play. + + Ham. One + + Laer. No + + Ham. Iudgement + + Osr. A hit, a very palpable hit + + Laer. Well: againe + + King. Stay, giue me drinke. +Hamlet, this Pearle is thine, +Here's to thy health. Giue him the cup, + +Trumpets sound, and shot goes off. + + Ham. Ile play this bout first, set by a-while. +Come: Another hit; what say you? + Laer. A touch, a touch, I do confesse + + King. Our Sonne shall win + + Qu. He's fat, and scant of breath. +Heere's a Napkin, rub thy browes, +The Queene Carowses to thy fortune, Hamlet + + Ham. Good Madam + + King. Gertrude, do not drinke + + Qu. I will my Lord; +I pray you pardon me + + King. It is the poyson'd Cup, it is too late + + Ham. I dare not drinke yet Madam, +By and by + + Qu. Come, let me wipe thy face + + Laer. My Lord, Ile hit him now + + King. I do not thinke't + + Laer. And yet 'tis almost 'gainst my conscience + + Ham. Come for the third. +Laertes, you but dally, +I pray you passe with your best violence, +I am affear'd you make a wanton of me + + Laer. Say you so? Come on. + +Play. + + Osr. Nothing neither way + + Laer. Haue at you now. + +In scuffling they change Rapiers. + + King. Part them, they are incens'd + + Ham. Nay come, againe + + Osr. Looke to the Queene there hoa + + Hor. They bleed on both sides. How is't my Lord? + Osr. How is't Laertes? + Laer. Why as a Woodcocke +To mine Sprindge, Osricke, +I am iustly kill'd with mine owne Treacherie + + Ham. How does the Queene? + King. She sounds to see them bleede + + Qu. No, no, the drinke, the drinke. +Oh my deere Hamlet, the drinke, the drinke, +I am poyson'd + + Ham. Oh Villany! How? Let the doore be lock'd. +Treacherie, seeke it out + + Laer. It is heere Hamlet. +Hamlet, thou art slaine, +No Medicine in the world can do thee good. +In thee, there is not halfe an houre of life; +The Treacherous Instrument is in thy hand, +Vnbated and envenom'd: the foule practise +Hath turn'd it selfe on me. Loe, heere I lye, +Neuer to rise againe: Thy Mothers poyson'd: +I can no more, the King, the King's too blame + + Ham. The point envenom'd too, +Then venome to thy worke. + +Hurts the King. + + All. Treason, Treason + + King. O yet defend me Friends, I am but hurt + + Ham. Heere thou incestuous, murdrous, +Damned Dane, +Drinke off this Potion: Is thy Vnion heere? +Follow my Mother. + +King Dyes. + + Laer. He is iustly seru'd. +It is a poyson temp'red by himselfe: +Exchange forgiuenesse with me, Noble Hamlet; +Mine and my Fathers death come not vpon thee, +Nor thine on me. + +Dyes. + + Ham. Heauen make thee free of it, I follow thee. +I am dead Horatio, wretched Queene adiew, +You that looke pale, and tremble at this chance, +That are but Mutes or audience to this acte: +Had I but time (as this fell Sergeant death +Is strick'd in his Arrest) oh I could tell you. +But let it be: Horatio, I am dead, +Thou liu'st, report me and my causes right +To the vnsatisfied + + Hor. Neuer beleeue it. +I am more an Antike Roman then a Dane: +Heere's yet some Liquor left + + Ham. As th'art a man, giue me the Cup. +Let go, by Heauen Ile haue't. +Oh good Horatio, what a wounded name, +(Things standing thus vnknowne) shall liue behind me. +If thou did'st euer hold me in thy heart, +Absent thee from felicitie awhile, +And in this harsh world draw thy breath in paine, +To tell my Storie. + +March afarre off, and shout within. + +What warlike noyse is this? +Enter Osricke. + + Osr. Yong Fortinbras, with conquest come fro[m] Poland +To th' Ambassadors of England giues this warlike volly + + Ham. O I dye Horatio: +The potent poyson quite ore-crowes my spirit, +I cannot liue to heare the Newes from England, +But I do prophesie th' election lights +On Fortinbras, he ha's my dying voyce, +So tell him with the occurrents more and lesse, +Which haue solicited. The rest is silence. O, o, o, o. + +Dyes + + Hora. Now cracke a Noble heart: +Goodnight sweet Prince, +And flights of Angels sing thee to thy rest, +Why do's the Drumme come hither? +Enter Fortinbras and English Ambassador, with Drumme, Colours, +and +Attendants. + + Fortin. Where is this sight? + Hor. What is it ye would see; +If ought of woe, or wonder, cease your search + + For. His quarry cries on hauocke. Oh proud death, +What feast is toward in thine eternall Cell. +That thou so many Princes, at a shoote, +So bloodily hast strooke + + Amb. The sight is dismall, +And our affaires from England come too late, +The eares are senselesse that should giue vs hearing, +To tell him his command'ment is fulfill'd, +That Rosincrance and Guildensterne are dead: +Where should we haue our thankes? + Hor. Not from his mouth, +Had it th' abilitie of life to thanke you: +He neuer gaue command'ment for their death. +But since so iumpe vpon this bloodie question, +You from the Polake warres, and you from England +Are heere arriued. Giue order that these bodies +High on a stage be placed to the view, +And let me speake to th' yet vnknowing world, +How these things came about. So shall you heare +Of carnall, bloudie, and vnnaturall acts, +Of accidentall iudgements, casuall slaughters +Of death's put on by cunning, and forc'd cause, +And in this vpshot, purposes mistooke, +Falne on the Inuentors head. All this can I +Truly deliuer + + For. Let vs hast to heare it, +And call the Noblest to the Audience. +For me, with sorrow, I embrace my Fortune, +I haue some Rites of memory in this Kingdome, +Which are to claime, my vantage doth +Inuite me, + Hor. Of that I shall haue alwayes cause to speake, +And from his mouth +Whose voyce will draw on more: +But let this same be presently perform'd, +Euen whiles mens mindes are wilde, +Lest more mischance +On plots, and errors happen + + For. Let foure Captaines +Beare Hamlet like a Soldier to the Stage, +For he was likely, had he beene put on +To haue prou'd most royally: +And for his passage, +The Souldiours Musicke, and the rites of Warre +Speake lowdly for him. +Take vp the body; Such a sight as this +Becomes the Field, but heere shewes much amis. +Go, bid the Souldiers shoote. + +Exeunt. Marching: after the which, a Peale of Ordenance are shot +off. + + +FINIS. The tragedie of HAMLET, Prince of Denmarke. diff --git a/java-strings-2/src/main/resources/stephenking.txt b/java-strings-2/src/main/resources/stephenking.txt new file mode 100644 index 0000000000..f31b4a28bd --- /dev/null +++ b/java-strings-2/src/main/resources/stephenking.txt @@ -0,0 +1,4 @@ +Get busy living +or +get busy dying. +--Stephen King \ No newline at end of file diff --git a/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java b/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java new file mode 100644 index 0000000000..50d9a2b058 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/initialization/StringInitializationUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.initialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import org.junit.Test; + +public class StringInitializationUnitTest { + + private String fieldString; + + void printDeclaredOnlyString() { + String localVarString = null; + + System.out.println(localVarString); // compilation error + System.out.println(fieldString); + } + + @Test + public void givenDeclaredFeldStringAndNullString_thenCompareEquals() { + String localVarString = null; + + assertEquals(fieldString, localVarString); + } + + @Test + public void givenTwoStringsWithSameLiteral_thenCompareReferencesEquals() { + String literalOne = "Baeldung"; + String literalTwo = "Baeldung"; + + assertTrue(literalOne == literalTwo); + } + + @Test + public void givenTwoStringsUsingNew_thenCompareReferencesNotEquals() { + String newStringOne = new String("Baeldung"); + String newStringTwo = new String("Baeldung"); + + assertFalse(newStringOne == newStringTwo); + } + + @Test + public void givenEmptyLiteralStringsAndNewObject_thenCompareEquals() { + String emptyLiteral = ""; + String emptyNewString = new String(""); + + assertEquals(emptyLiteral, emptyNewString); + } + + @Test + public void givenEmptyStringObjects_thenCompareEquals() { + String emptyNewString = new String(""); + String emptyNewStringTwo = new String(); + + assertEquals(emptyNewString, emptyNewStringTwo); + } +} diff --git a/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java b/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java new file mode 100644 index 0000000000..2c8f9b47f3 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.localization; + +import static org.junit.Assert.assertEquals; + +import java.util.Locale; + +import org.junit.Test; + +import com.baeldung.localization.ICUFormat; + +public class ICUFormatUnitTest { + + @Test + public void givenInUK_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice has sent you no messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInUK_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice has sent you a message.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInUK_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob has sent you 6 messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInItaly_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice non ti ha inviato nessun messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInItaly_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice ti ha inviato un messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInItaly_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob ti ha inviato 6 messaggi.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInFrance_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice ne vous a envoyé aucun message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInFrance_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice vous a envoyé un message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInFrance_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob vous a envoyé 6 messages.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Bob", "male", 6 })); + } + + + @Test + public void givenInPoland_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice nie wysłała ci żadnej wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInPoland_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice wysłała ci wiadomość.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInPoland_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob wysłał ci 6 wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Bob", "male", 6 })); + } + +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/MultiLineStringUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/MultiLineStringUnitTest.java new file mode 100644 index 0000000000..b458fae79b --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/MultiLineStringUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.string; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import com.baeldung.string.multiline.MultiLineString; + +public class MultiLineStringUnitTest { + + + @Test + public void whenCompareMultiLineStrings_thenTheyAreAllTheSame() throws IOException { + MultiLineString ms = new MultiLineString(); + assertEquals(ms.stringConcatenation(), ms.stringJoin()); + assertEquals(ms.stringJoin(), ms.stringBuilder()); + assertEquals(ms.stringBuilder(), ms.guavaJoiner()); + assertEquals(ms.guavaJoiner(), ms.loadFromFile()); + } + +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/RemoveStopwordsUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/RemoveStopwordsUnitTest.java new file mode 100644 index 0000000000..edda2ec9d7 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/RemoveStopwordsUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.string; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class RemoveStopwordsUnitTest { + final String original = "The quick brown fox jumps over the lazy dog"; + final String target = "quick brown fox jumps lazy dog"; + static List stopwords; + + @BeforeClass + public static void loadStopwords() throws IOException { + stopwords = Files.readAllLines(Paths.get("src/main/resources/english_stopwords.txt")); + } + + @Test + public void whenRemoveStopwordsManually_thenSuccess() { + String[] allWords = original.toLowerCase() + .split(" "); + StringBuilder builder = new StringBuilder(); + for (String word : allWords) { + if (!stopwords.contains(word)) { + builder.append(word); + builder.append(' '); + } + } + + String result = builder.toString().trim(); + assertEquals(result, target); + } + + @Test + public void whenRemoveStopwordsUsingRemoveAll_thenSuccess() { + ArrayList allWords = Stream.of(original.toLowerCase() + .split(" ")) + .collect(Collectors.toCollection(ArrayList::new)); + allWords.removeAll(stopwords); + String result = allWords.stream().collect(Collectors.joining(" ")); + assertEquals(result, target); + } + + @Test + public void whenRemoveStopwordsUsingRegex_thenSuccess() { + String stopwordsRegex = stopwords.stream() + .collect(Collectors.joining("|", "\\b(", ")\\b\\s?")); + String result = original.toLowerCase().replaceAll(stopwordsRegex, ""); + assertEquals(result, target); + } + +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/emptystrings/EmptyStringsUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/emptystrings/EmptyStringsUnitTest.java new file mode 100644 index 0000000000..96b1d681dd --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/emptystrings/EmptyStringsUnitTest.java @@ -0,0 +1,142 @@ +package com.baeldung.string.emptystrings; + +import static org.hamcrest.Matchers.iterableWithSize; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import com.google.common.base.Strings; + +public class EmptyStringsUnitTest { + + private String emptyString = ""; + private String blankString = " \n\t "; + private String nonEmptyString = " someString "; + + /* + * EmptyStringCheck + */ + @Test + public void givenSomeEmptyString_thenEmptyStringCheckIsEmptyStringReturnsTrue() { + assertTrue(new EmptyStringCheck().isEmptyString(emptyString)); + } + + @Test + public void givenSomeNonEmptyString_thenEmptyStringCheckIsEmptyStringReturnsFalse() { + assertFalse(new EmptyStringCheck().isEmptyString(nonEmptyString)); + } + + @Test + public void givenSomeBlankString_thenEmptyStringCheckIsEmptyStringReturnsFalse() { + assertFalse(new EmptyStringCheck().isEmptyString(blankString)); + } + + /* + * Java5EmptyStringCheck + */ + @Test + public void givenSomeEmptyString_thenJava5EmptyStringCheckIsEmptyStringReturnsTrue() { + assertTrue(new Java5EmptyStringCheck().isEmptyString(emptyString)); + } + + @Test + public void givenSomeNonEmptyString_thenJava5EmptyStringCheckIsEmptyStringReturnsFalse() { + assertFalse(new Java5EmptyStringCheck().isEmptyString(nonEmptyString)); + } + + @Test + public void givenSomeBlankString_thenJava5EmptyStringCheckIsEmptyStringReturnsFalse() { + assertFalse(new Java5EmptyStringCheck().isEmptyString(blankString)); + } + + /* + * PlainJavaBlankStringCheck + */ + @Test + public void givenSomeEmptyString_thenPlainJavaBlankStringCheckIsBlankStringReturnsTrue() { + assertTrue(new PlainJavaBlankStringCheck().isBlankString(emptyString)); + } + + @Test + public void givenSomeNonEmptyString_thenPlainJavaBlankStringCheckIsBlankStringReturnsFalse() { + assertFalse(new PlainJavaBlankStringCheck().isBlankString(nonEmptyString)); + } + + @Test + public void givenSomeBlankString_thenPlainJavaBlankStringCheckIsBlankStringReturnsTrue() { + assertTrue(new PlainJavaBlankStringCheck().isBlankString(blankString)); + } + + /* + * Apache Commons Lang StringUtils + */ + @Test + public void givenSomeEmptyString_thenStringUtilsIsBlankReturnsTrue() { + assertTrue(StringUtils.isBlank(emptyString)); + } + + @Test + public void givenSomeNonEmptyString_thenStringUtilsIsBlankReturnsFalse() { + assertFalse(StringUtils.isBlank(nonEmptyString)); + } + + @Test + public void givenSomeBlankString_thenStringUtilsIsBlankReturnsTrue() { + assertTrue(StringUtils.isBlank(blankString)); + } + + /* + * Google Guava Strings + */ + @Test + public void givenSomeEmptyString_thenStringsIsNullOrEmptyStringReturnsTrue() { + assertTrue(Strings.isNullOrEmpty(emptyString)); + } + + @Test + public void givenSomeNonEmptyString_thenStringsIsNullOrEmptyStringReturnsFalse() { + assertFalse(Strings.isNullOrEmpty(nonEmptyString)); + } + + @Test + public void givenSomeBlankString_thenStringsIsNullOrEmptyStringReturnsFalse() { + assertFalse(Strings.isNullOrEmpty(blankString)); + } + + /* + * Bean Validation + */ + private ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + private Validator validator = factory.getValidator(); + + @Test + public void givenSomeEmptyString_thenBeanValidationReturnsViolations() { + SomeClassWithValidations someClassWithValidations = new SomeClassWithValidations().setSomeString(emptyString); + Set> violations = validator.validate(someClassWithValidations); + assertThat(violations, iterableWithSize(1)); + } + + @Test + public void givenSomeNonEmptyString_thenBeanValidationValidatesWithoutViolations() { + SomeClassWithValidations someClassWithValidations = new SomeClassWithValidations().setSomeString(nonEmptyString); + Set> violations = validator.validate(someClassWithValidations); + assertThat(violations, iterableWithSize(0)); + } + + @Test + public void givenSomeBlankString_thenBeanValidationReturnsViolations() { + SomeClassWithValidations someClassWithValidations = new SomeClassWithValidations().setSomeString(blankString); + Set> violations = validator.validate(someClassWithValidations); + assertThat(violations, iterableWithSize(1)); + } +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/repetition/SubstringRepetitionUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/repetition/SubstringRepetitionUnitTest.java new file mode 100644 index 0000000000..f382a24a7f --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/repetition/SubstringRepetitionUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.string.repetition; + +import static com.baeldung.string.repetition.SubstringRepetition.*; +import static org.junit.Assert.*; + +import org.junit.Test; + +public class SubstringRepetitionUnitTest { + + private String validString = "aa"; + private String validStringTwo = "ababab"; + private String validStringThree = "baeldungbaeldung"; + + private String invalidString = "aca"; + private String invalidStringTwo = "ababa"; + private String invalidStringThree = "baeldungnonrepeatedbaeldung"; + + @Test + public void givenValidStrings_whenCheckIfContainsOnlySubstrings_thenReturnsTrue() { + assertTrue(containsOnlySubstrings(validString)); + assertTrue(containsOnlySubstrings(validStringTwo)); + assertTrue(containsOnlySubstrings(validStringThree)); + } + + @Test + public void givenInvalidStrings_whenCheckIfContainsOnlySubstrings_thenReturnsFalse() { + assertFalse(containsOnlySubstrings(invalidString)); + assertFalse(containsOnlySubstrings(invalidStringTwo)); + assertFalse(containsOnlySubstrings(invalidStringThree)); + } + + @Test + public void givenValidStrings_whenCheckEfficientlyIfContainsOnlySubstrings_thenReturnsTrue() { + assertTrue(containsOnlySubstringsEfficient(validString)); + assertTrue(containsOnlySubstringsEfficient(validStringTwo)); + assertTrue(containsOnlySubstringsEfficient(validStringThree)); + } + + @Test + public void givenInvalidStrings_whenCheckEfficientlyIfContainsOnlySubstrings_thenReturnsFalse() { + assertFalse(containsOnlySubstringsEfficient(invalidString)); + assertFalse(containsOnlySubstringsEfficient(invalidStringTwo)); + assertFalse(containsOnlySubstringsEfficient(invalidStringThree)); + } +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/reverse/ReverseStringExamplesUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/reverse/ReverseStringExamplesUnitTest.java new file mode 100644 index 0000000000..020ead02db --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/reverse/ReverseStringExamplesUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.string.reverse; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ReverseStringExamplesUnitTest { + + private static final String STRING_INPUT = "cat"; + private static final String STRING_INPUT_REVERSED = "tac"; + private static final String SENTENCE = "The quick brown fox jumps over the lazy dog"; + private static final String REVERSED_WORDS_SENTENCE = "dog lazy the over jumps fox brown quick The"; + + @Test + public void whenReverseIsCalled_ThenCorrectStringIsReturned() { + String reversed = ReverseStringExamples.reverse(STRING_INPUT); + String reversedNull = ReverseStringExamples.reverse(null); + String reversedEmpty = ReverseStringExamples.reverse(StringUtils.EMPTY); + + assertEquals(STRING_INPUT_REVERSED, reversed); + assertEquals(null, reversedNull); + assertEquals(StringUtils.EMPTY, reversedEmpty); + } + + @Test + public void whenReverseUsingStringBuilderIsCalled_ThenCorrectStringIsReturned() throws Exception { + String reversed = ReverseStringExamples.reverseUsingStringBuilder(STRING_INPUT); + String reversedNull = ReverseStringExamples.reverseUsingStringBuilder(null); + String reversedEmpty = ReverseStringExamples.reverseUsingStringBuilder(StringUtils.EMPTY); + + assertEquals(STRING_INPUT_REVERSED, reversed); + assertEquals(null, reversedNull); + assertEquals(StringUtils.EMPTY, reversedEmpty); + } + + @Test + public void whenReverseUsingApacheCommonsIsCalled_ThenCorrectStringIsReturned() throws Exception { + String reversed = ReverseStringExamples.reverseUsingApacheCommons(STRING_INPUT); + String reversedNull = ReverseStringExamples.reverseUsingApacheCommons(null); + String reversedEmpty = ReverseStringExamples.reverseUsingApacheCommons(StringUtils.EMPTY); + + assertEquals(STRING_INPUT_REVERSED, reversed); + assertEquals(null, reversedNull); + assertEquals(StringUtils.EMPTY, reversedEmpty); + } + + @Test + public void whenReverseTheOrderOfWordsIsCalled_ThenCorrectStringIsReturned() { + String reversed = ReverseStringExamples.reverseTheOrderOfWords(SENTENCE); + String reversedNull = ReverseStringExamples.reverseTheOrderOfWords(null); + String reversedEmpty = ReverseStringExamples.reverseTheOrderOfWords(StringUtils.EMPTY); + + assertEquals(REVERSED_WORDS_SENTENCE, reversed); + assertEquals(null, reversedNull); + assertEquals(StringUtils.EMPTY, reversedEmpty); + } + + @Test + public void whenReverseTheOrderOfWordsUsingApacheCommonsIsCalled_ThenCorrectStringIsReturned() { + String reversed = ReverseStringExamples.reverseTheOrderOfWordsUsingApacheCommons(SENTENCE); + String reversedNull = ReverseStringExamples.reverseTheOrderOfWordsUsingApacheCommons(null); + String reversedEmpty = ReverseStringExamples.reverseTheOrderOfWordsUsingApacheCommons(StringUtils.EMPTY); + + assertEquals(REVERSED_WORDS_SENTENCE, reversed); + assertEquals(null, reversedNull); + assertEquals(StringUtils.EMPTY, reversedEmpty); + } + +} diff --git a/java-strings-2/src/test/java/com/baeldung/string/search/SubstringSearchUnitTest.java b/java-strings-2/src/test/java/com/baeldung/string/search/SubstringSearchUnitTest.java new file mode 100644 index 0000000000..293e6d2125 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/string/search/SubstringSearchUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.string.search; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +/** + * BAEL-2832: Different ways to check if a Substring could be found in a String. + */ +public class SubstringSearchUnitTest { + + @Test + public void searchSubstringWithIndexOf() { + Assert.assertEquals(9, "Bohemian Rhapsodyan".indexOf("Rhap")); + + // indexOf will return -1, because it's case sensitive + Assert.assertEquals(-1, "Bohemian Rhapsodyan".indexOf("rhap")); + + // indexOf will return 9, because it's all lowercase + Assert.assertEquals(9, "Bohemian Rhapsodyan".toLowerCase() + .indexOf("rhap")); + + // it will return 6, because it's the first occurrence. Sorry Queen for being blasphemic + Assert.assertEquals(6, "Bohemian Rhapsodyan".indexOf("an")); + } + + @Test + public void searchSubstringWithContains() { + Assert.assertTrue("Hey Ho, let's go".contains("Hey")); + + // contains will return false, because it's case sensitive + Assert.assertFalse("Hey Ho, let's go".contains("hey")); + + // contains will return true, because it's all lowercase + Assert.assertTrue("Hey Ho, let's go".toLowerCase().contains("hey")); + + // contains will return false, because 'jey' can't be found + Assert.assertFalse("Hey Ho, let's go".contains("jey")); + } + + @Test + public void searchSubstringWithStringUtils() { + Assert.assertTrue(StringUtils.containsIgnoreCase("Runaway train", "train")); + + // it will also be true, because ignores case ;) + Assert.assertTrue(StringUtils.containsIgnoreCase("Runaway train", "Train")); + } + + @Test + public void searchUsingPattern() { + + // We create the Pattern first + Pattern pattern = Pattern.compile("(? org.openjdk.jmh jmh-generator-annprocess - ${jmh-core.version} + ${jmh-generator.version} com.ibm.icu @@ -66,20 +66,20 @@ com.vdurmont emoji-java - 4.0.0 + ${emoji-java.version} org.junit.jupiter junit-jupiter-api - 5.3.1 + ${junit-jupiter-api.version} test org.hamcrest hamcrest-library - 1.3 + ${org.hamcrest.version} test @@ -87,12 +87,18 @@ org.passay passay - 1.3.1 + ${passay.version} org.apache.commons commons-text - 1.4 + ${commons-text.version} + + + + org.ahocorasick + ahocorasick + ${ahocorasick.version} @@ -110,10 +116,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + ${maven-compiler-plugin.version} - 1.8 - 1.8 + ${java.version} + ${java.version} -parameters @@ -126,9 +132,13 @@ 1.10 3.6.1 - 1.19 61.1 27.0.1-jre + 4.0.0 + 5.3.1 + 1.3.1 + 1.4 + 0.4.0 diff --git a/core-java/src/main/java/com/baeldung/string/AppendCharAtPositionX.java b/java-strings/src/main/java/com/baeldung/string/AppendCharAtPositionX.java similarity index 100% rename from core-java/src/main/java/com/baeldung/string/AppendCharAtPositionX.java rename to java-strings/src/main/java/com/baeldung/string/AppendCharAtPositionX.java diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java new file mode 100644 index 0000000000..0cad52c320 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -0,0 +1,83 @@ +package com.baeldung.string; + +import org.ahocorasick.trie.Emit; +import org.ahocorasick.trie.Token; +import org.ahocorasick.trie.Trie; + +import java.util.*; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class MatchWords { + + public static boolean containsWordsIndexOf(String inputString, String[] words) { + boolean found = true; + for (String word : words) { + if (inputString.indexOf(word) == -1) { + found = false; + break; + } + } + return found; + } + + public static boolean containsWords(String inputString, String[] items) { + boolean found = true; + for (String item : items) { + if (!inputString.contains(item)) { + found = false; + break; + } + } + return found; + } + + public static boolean containsWordsAhoCorasick(String inputString, String[] words) { + Trie trie = Trie.builder() + .onlyWholeWords() + .addKeywords(words) + .build(); + + Collection emits = trie.parseText(inputString); + emits.forEach(System.out::println); + + boolean found = true; + for(String word : words) { + boolean contains = Arrays.toString(emits.toArray()).contains(word); + if (!contains) { + found = false; + break; + } + } + + return found; + } + + public static boolean containsWordsPatternMatch(String inputString, String[] words) { + + StringBuilder regexp = new StringBuilder(); + for (String word : words) { + regexp.append("(?=.*").append(word).append(")"); + } + + Pattern pattern = Pattern.compile(regexp.toString()); + + return pattern.matcher(inputString).find(); + } + + public static boolean containsWordsJava8(String inputString, String[] words) { + List inputStringList = Arrays.asList(inputString.split(" ")); + List wordsList = Arrays.asList(words); + + return wordsList.stream().allMatch(inputStringList::contains); + } + + public static boolean containsWordsArray(String inputString, String[] words) { + List inputStringList = Arrays.asList(inputString.split(" ")); + List wordsList = Arrays.asList(words); + + return inputStringList.containsAll(wordsList); + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/Pangram.java b/java-strings/src/main/java/com/baeldung/string/Pangram.java new file mode 100644 index 0000000000..c09b0c1d29 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/Pangram.java @@ -0,0 +1,61 @@ +package com.baeldung.string; + +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Pangram { + private static final int ALPHABET_COUNT = 26; + + public static boolean isPangram(String str) { + if (str == null) + return false; + Boolean[] alphabetMarker = new Boolean[ALPHABET_COUNT]; + Arrays.fill(alphabetMarker, false); + int alphabetIndex = 0; + String strUpper = str.toUpperCase(); + for (int i = 0; i < str.length(); i++) { + if ('A' <= strUpper.charAt(i) && strUpper.charAt(i) <= 'Z') { + alphabetIndex = strUpper.charAt(i) - 'A'; + alphabetMarker[alphabetIndex] = true; + } + } + for (boolean index : alphabetMarker) { + if (!index) + return false; + } + return true; + } + + public static boolean isPangramWithStreams(String str) { + if (str == null) + return false; + + // filtered character stream + String strUpper = str.toUpperCase(); + Stream filteredCharStream = strUpper.chars() + .filter(item -> ((item >= 'A' && item <= 'Z'))) + .mapToObj(c -> (char) c); + Map alphabetMap = filteredCharStream.collect(Collectors.toMap(item -> item, k -> Boolean.TRUE, (p1, p2) -> p1)); + + return (alphabetMap.size() == ALPHABET_COUNT); + } + + public static boolean isPerfectPangram(String str) { + if (str == null) + return false; + + // filtered character stream + String strUpper = str.toUpperCase(); + Stream filteredCharStream = strUpper.chars() + .filter(item -> ((item >= 'A' && item <= 'Z'))) + .mapToObj(c -> (char) c); + Map alphabetFrequencyMap = filteredCharStream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + return (alphabetFrequencyMap.size() == ALPHABET_COUNT && alphabetFrequencyMap.values() + .stream() + .allMatch(item -> item == 1)); + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/ReplaceCharacterInString.java b/java-strings/src/main/java/com/baeldung/string/ReplaceCharacterInString.java new file mode 100644 index 0000000000..2cc67f0b51 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/ReplaceCharacterInString.java @@ -0,0 +1,29 @@ +package com.baeldung.string; + +public class ReplaceCharacterInString { + + public String replaceCharSubstring(String str, char ch, int index) { + String myString = str.substring(0, index) + ch + str.substring(index + 1); + return myString; + } + + public String replaceCharUsingCharArray(String str, char ch, int index) { + char[] chars = str.toCharArray(); + chars[index] = ch; + return String.valueOf(chars); + } + + + public String replaceCharStringBuilder(String str, char ch, int index) { + StringBuilder myString = new StringBuilder(str); + myString.setCharAt(index, ch); + return myString.toString(); + } + + public String replaceCharStringBuffer(String str, char ch, int index) { + StringBuffer myString = new StringBuffer(str); + myString.setCharAt(index, ch); + return myString.toString(); + } + +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java b/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java new file mode 100644 index 0000000000..e914a83f0e --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java @@ -0,0 +1,19 @@ +package com.baeldung.string.tostring; + +public class Customer { + private String firstName; + private String 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; + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java new file mode 100644 index 0000000000..1736657276 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java @@ -0,0 +1,19 @@ +package com.baeldung.string.tostring; + +import java.util.Arrays; + +public class CustomerArrayToString extends Customer { + private Order[] orders; + + public Order[] getOrders() { + return orders; + } + public void setOrders(Order[] orders) { + this.orders = orders; + } + @Override + public String toString() { + return "Customer [orders=" + Arrays.toString(orders) + ", getFirstName()=" + getFirstName() + + ", getLastName()=" + getLastName() + "]"; + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java new file mode 100644 index 0000000000..9bede1b3fc --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java @@ -0,0 +1,19 @@ +package com.baeldung.string.tostring; + +public class CustomerComplexObjectToString extends Customer { + private Order order; + + public Order getOrder() { + return order; + } + + public void setOrder(Order order) { + this.order = order; + } + + @Override + public String toString() { + return "Customer [order=" + order + ", getFirstName()=" + getFirstName() + + ", getLastName()=" + getLastName() + "]"; + } +} \ No newline at end of file diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java new file mode 100644 index 0000000000..86e08ca447 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java @@ -0,0 +1,19 @@ +package com.baeldung.string.tostring; + +public class CustomerPrimitiveToString extends Customer { + private long balance; + + public long getBalance() { + return balance; + } + + public void setBalance(long balance) { + this.balance = balance; + } + + @Override + public String toString() { + return "Customer [balance=" + balance + ", getFirstName()=" + getFirstName() + + ", getLastName()=" + getLastName() + "]"; + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java new file mode 100644 index 0000000000..2da1163c63 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java @@ -0,0 +1,41 @@ +package com.baeldung.string.tostring; + +import java.util.List; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +public class CustomerReflectionToString extends Customer{ + + private Integer score; + private List orders; + private StringBuffer fullname; + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public List getOrders() { + return orders; + } + + public void setOrders(List orders) { + this.orders = orders; + } + + public StringBuffer getFullname() { + return fullname; + } + + public void setFullname(StringBuffer fullname) { + this.fullname = fullname; + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java new file mode 100644 index 0000000000..6c7b999045 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java @@ -0,0 +1,39 @@ +package com.baeldung.string.tostring; + +import java.util.List; + +public class CustomerWrapperCollectionToString extends Customer { + private Integer score; + private List orders; + private StringBuffer fullname; + + public Integer getScore() { + return score; + } + + public void setScore(Integer score) { + this.score = score; + } + + public List getOrders() { + return orders; + } + + public void setOrders(List orders) { + this.orders = orders; + } + + public StringBuffer getFullname() { + return fullname; + } + + public void setFullname(StringBuffer fullname) { + this.fullname = fullname; + } + + @Override + public String toString() { + return "Customer [score=" + score + ", orders=" + orders + ", fullname=" + fullname + + ", getFirstName()=" + getFirstName() + ", getLastName()=" + getLastName() + "]"; + } +} diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/Order.java b/java-strings/src/main/java/com/baeldung/string/tostring/Order.java new file mode 100644 index 0000000000..017e2d9bc8 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/tostring/Order.java @@ -0,0 +1,46 @@ +package com.baeldung.string.tostring; + +public class Order { + + private String orderId; + private String desc; + private long value; + private String status; + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public long getValue() { + return value; + } + + public void setValue(long value) { + this.value = value; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + @Override + public String toString() { + return "Order [orderId=" + orderId + ", desc=" + desc + ", value=" + value + "]"; + } + +} diff --git a/java-strings/src/test/java/com/baeldung/StringConcatenationUnitTest.java b/java-strings/src/test/java/com/baeldung/StringConcatenationUnitTest.java new file mode 100644 index 0000000000..c25d4ce8f9 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/StringConcatenationUnitTest.java @@ -0,0 +1,105 @@ +package com.baeldung; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.StringJoiner; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +public class StringConcatenationUnitTest { + + @Test + public void givenMultipleStrings_whenConcatUsingStringBuilder_checkStringCorrect() { + + StringBuilder stringBuilder = new StringBuilder(100); + stringBuilder.append("Baeldung"); + stringBuilder.append(" is"); + stringBuilder.append(" awesome"); + + assertEquals("Baeldung is awesome", stringBuilder.toString()); + + } + + @Test + public void givenMultipleString_whenConcatUsingAdditionOperator_checkStringCorrect() { + + String myString = "The " + "quick " + "brown " + "fox..."; + + assertEquals("The quick brown fox...", myString); + } + + + @Test + public void givenMultipleStrings_whenConcatUsingStringFormat_checkStringCorrect() { + + String myString = String.format("%s %s %.2f %s %s, %s...", "I", + "ate", + 2.5056302, + "blueberry", + "pies", + "oops"); + + + assertEquals("I ate 2.51 blueberry pies, oops...", myString); + } + + @Test + public void givenMultipleStrings_whenStringConcatUsed_checkStringCorrect() { + + String myString = "Both".concat(" fickle") + .concat(" dwarves") + .concat(" jinx") + .concat(" my") + .concat(" pig") + .concat(" quiz"); + + assertEquals("Both fickle dwarves jinx my pig quiz", myString); + + + } + + @Test + public void givenMultipleStrings_whenStringJoinUsed_checkStringCorrect() { + + String[] strings = {"I'm", "running", "out", "of", "pangrams!"}; + + String myString = String.join(" ", strings); + + assertEquals("I'm running out of pangrams!", myString); + + } + + @Test + public void givenMultipleStrings_whenStringJoinerUsed_checkStringCorrect() { + + StringJoiner fruitJoiner = new StringJoiner(", "); + fruitJoiner.add("Apples"); + fruitJoiner.add("Oranges"); + fruitJoiner.add("Bananas"); + + assertEquals("Apples, Oranges, Bananas", fruitJoiner.toString()); + } + + @Test + public void givenMultipleStrings_whenArrayJoiner_checkStringCorrect() { + + String[] myFavouriteLanguages = {"Java", "JavaScript", "Python"}; + + String toString = Arrays.toString(myFavouriteLanguages); + + assertEquals("[Java, JavaScript, Python]", toString); + } + + @Test + public void givenArrayListOfStrings_whenCollectorsJoin_checkStringCorrect() { + + List awesomeAnimals = Arrays.asList("Shark", "Panda", "Armadillo"); + + String animalString = awesomeAnimals.stream().collect(Collectors.joining(", ")); + + assertEquals("Shark, Panda, Armadillo", animalString); + } +} diff --git a/core-java/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java b/java-strings/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java rename to java-strings/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java diff --git a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java new file mode 100644 index 0000000000..385aadaa5d --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.string; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MatchWordsUnitTest { + + private final String[] words = {"hello", "Baeldung"}; + private final String inputString = "hello there, Baeldung"; + private final String wholeInput = "helloBaeldung"; + + @Test + public void givenText_whenCallingStringContains_shouldMatchWords() { + final boolean result = MatchWords.containsWords(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingJava8_shouldMatchWords() { + final boolean result = MatchWords.containsWordsJava8(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingJava8_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsJava8(wholeInput, words); + assertThat(result).isFalse(); + } + + @Test + public void givenText_whenCallingPattern_shouldMatchWords() { + final boolean result = MatchWords.containsWordsPatternMatch(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingAhoCorasick_shouldMatchWords() { + final boolean result = MatchWords.containsWordsAhoCorasick(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingAhoCorasick_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsAhoCorasick(wholeInput, words); + assertThat(result).isFalse(); + } + + @Test + public void givenText_whenCallingIndexOf_shouldMatchWords() { + final boolean result = MatchWords.containsWordsIndexOf(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingArrayList_shouldMatchWords() { + final boolean result = MatchWords.containsWordsArray(inputString, words); + assertThat(result).isTrue(); + } + + @Test + public void givenText_whenCallingArrayList_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsArray(wholeInput, words); + assertThat(result).isFalse(); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java b/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java new file mode 100644 index 0000000000..36e603b535 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.string; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +public class PangramUnitTest { + + @Test + public void givenValidString_isPangram_shouldReturnSuccess() { + String input = "Two driven jocks help fax my big quiz"; + assertTrue(Pangram.isPangram(input)); + assertTrue(Pangram.isPangramWithStreams(input)); + } + + @Test + public void givenNullString_isPangram_shouldReturnFailure() { + String input = null; + assertFalse(Pangram.isPangram(input)); + assertFalse(Pangram.isPangramWithStreams(input)); + assertFalse(Pangram.isPerfectPangram(input)); + } + + @Test + public void givenPerfectPangramString_isPerfectPangram_shouldReturnSuccess() { + String input = "abcdefghijklmNoPqrStuVwxyz"; + assertTrue(Pangram.isPerfectPangram(input)); + } + + @Test + public void givenNonPangramString_isPangram_shouldReturnFailure() { + String input = "invalid pangram"; + assertFalse(Pangram.isPangram(input)); + assertFalse(Pangram.isPangramWithStreams(input)); + } + + @Test + public void givenPangram_isPerfectPangram_shouldReturnFailure() { + String input = "Two driven jocks help fax my big quiz"; + assertFalse(Pangram.isPerfectPangram(input)); + } + +} diff --git a/java-strings/src/test/java/com/baeldung/string/ReplaceCharInStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/ReplaceCharInStringUnitTest.java new file mode 100644 index 0000000000..c234c6953c --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/ReplaceCharInStringUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.string; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ReplaceCharInStringUnitTest { + private ReplaceCharacterInString characterInString = new ReplaceCharacterInString(); + + @Test + public void whenReplaceCharAtIndexUsingSubstring_thenSuccess() { + assertEquals("abcme", characterInString.replaceCharSubstring("abcde", 'm', 3)); + } + + @Test + public void whenReplaceCharAtIndexUsingCharArray_thenSuccess() { + assertEquals("abcme", characterInString.replaceCharUsingCharArray("abcde", 'm', 3)); + } + + @Test + public void whenReplaceCharAtIndexUsingStringBuilder_thenSuccess() { + assertEquals("abcme", characterInString.replaceCharStringBuilder("abcde", 'm', 3)); + } + + @Test + public void whenReplaceCharAtIndexUsingStringBuffer_thenSuccess() { + assertEquals("abcme", characterInString.replaceCharStringBuffer("abcde", 'm', 3)); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java index d952d2383b..4d2b54241b 100644 --- a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java @@ -1,7 +1,7 @@ package com.baeldung.string; - import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.RegExUtils; import org.junit.Test; import static org.junit.Assert.assertFalse; @@ -9,7 +9,6 @@ import static org.junit.Assert.assertTrue; public class StringReplaceAndRemoveUnitTest { - @Test public void givenTestStrings_whenReplace_thenProcessedString() { @@ -26,7 +25,7 @@ public class StringReplaceAndRemoveUnitTest { public void givenTestStrings_whenReplaceAll_thenProcessedString() { String master2 = "Welcome to Baeldung, Hello World Baeldung"; - String regexTarget= "(Baeldung)$"; + String regexTarget = "(Baeldung)$"; String replacement = "Java"; String processed2 = master2.replaceAll(regexTarget, replacement); assertTrue(processed2.endsWith("Java")); @@ -45,18 +44,16 @@ public class StringReplaceAndRemoveUnitTest { StringBuilder builder = new StringBuilder(master); - builder.delete(startIndex, stopIndex); - assertFalse(builder.toString().contains(target)); - + assertFalse(builder.toString() + .contains(target)); builder.replace(startIndex, stopIndex, replacement); - assertTrue(builder.toString().contains(replacement)); - + assertTrue(builder.toString() + .contains(replacement)); } - @Test public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() { @@ -74,10 +71,20 @@ public class StringReplaceAndRemoveUnitTest { } + @Test + public void givenTestStrings_whenReplaceExactWord_thenProcessedString() { + String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!"; + String regexTarget = "\\bcar\\b"; + String exactWordReplaced = sentence.replaceAll(regexTarget, "truck"); + assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced)); + } - - - - + @Test + public void givenTestStrings_whenReplaceExactWordUsingRegExUtilsMethod_thenProcessedString() { + String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!"; + String regexTarget = "\\bcar\\b"; + String exactWordReplaced = RegExUtils.replaceAll(sentence, regexTarget, "truck"); + assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced)); + } } diff --git a/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java b/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java index f236c641c3..d760510c73 100644 --- a/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java @@ -1,7 +1,6 @@ package com.baeldung.string.formatter; -import org.junit.BeforeClass; -import org.junit.Test; +import static org.junit.Assert.assertEquals; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -11,9 +10,11 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; +import java.util.Locale; import java.util.TimeZone; -import static org.junit.Assert.assertEquals; +import org.junit.BeforeClass; +import org.junit.Test; public class DateToStringFormatterUnitTest { @@ -40,7 +41,7 @@ public class DateToStringFormatterUnitTest { @Test public void whenDateConvertedUsingDateFormatToString_thenCorrect() { String formattedDate = DateFormat - .getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT) + .getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.US) .format(date); assertEquals(EXPECTED_STRING_DATE, formattedDate); diff --git a/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java new file mode 100644 index 0000000000..1d221056fd --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.string.interview; + +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.util.Locale; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class LocaleUnitTest { + @Test + public void whenUsingLocal_thenCorrectResultsForDifferentLocale() { + Locale usLocale = Locale.US; + BigDecimal number = new BigDecimal(102_300.456d); + + NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance(usLocale); + assertEquals(usNumberFormat.format(number), "$102,300.46"); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java new file mode 100644 index 0000000000..aadfade737 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.string.interview; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; + +import org.junit.Test; + +public class StringAnagramUnitTest { + public boolean isAnagram(String s1, String s2) { + if(s1.length() != s2.length()) + return false; + + char[] arr1 = s1.toCharArray(); + char[] arr2 = s2.toCharArray(); + + Arrays.sort(arr1); + Arrays.sort(arr2); + + return Arrays.equals(arr1, arr2); + } + + @Test + public void whenTestAnagrams_thenTestingCorrectly() { + assertThat(isAnagram("car", "arc")).isTrue(); + assertThat(isAnagram("west", "stew")).isTrue(); + assertThat(isAnagram("west", "east")).isFalse(); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java new file mode 100644 index 0000000000..2c7ec500fe --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StringChangeCaseUnitTest { + @Test + public void givenString_whenChangingToUppercase_thenCaseChanged() { + String s = "Welcome to Baeldung!"; + assertEquals("WELCOME TO BAELDUNG!", s.toUpperCase()); + } + + + @Test + public void givenString_whenChangingToLowerrcase_thenCaseChanged() { + String s = "Welcome to Baeldung!"; + assertEquals("welcome to baeldung!", s.toLowerCase()); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java new file mode 100644 index 0000000000..6c17643ac8 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StringCountOccurrencesUnitTest { + public int countOccurrences(String s, char c) { + int count = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == c) { + count++; + } + } + return count; + } + + @Test + public void givenString_whenCountingFrequencyOfChar_thenCountCorrect() { + assertEquals(3, countOccurrences("united states", 't')); + } + + public void givenString_whenUsingJava8_thenCountingOfCharCorrect() { + String str = "united states"; + long count = str.chars().filter(ch -> (char)ch == 't').count(); + assertEquals(3, count); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java new file mode 100644 index 0000000000..787017791c --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java @@ -0,0 +1,14 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StringFormatUnitTest { + @Test + public void givenString_whenUsingStringFormat_thenStringFormatted() { + String title = "Baeldung"; + String formatted = String.format("Title is %s", title); + assertEquals(formatted, "Title is Baeldung"); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java new file mode 100644 index 0000000000..c5bffb7573 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.string.interview; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class StringInternUnitTest { + @Test + public void whenCallingStringIntern_thenStringsInterned() { + String s1 = "Baeldung"; + String s2 = new String("Baeldung"); + String s3 = new String("Baeldung").intern(); + + assertThat(s1 == s2).isFalse(); + assertThat(s1 == s3).isTrue(); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java new file mode 100644 index 0000000000..d44c7478e4 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.string.interview; + +import java.util.StringJoiner; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StringJoinerUnitTest { + @Test + public void whenUsingStringJoiner_thenStringsJoined() { + StringJoiner joiner = new StringJoiner(",", "[", "]"); + joiner.add("Red") + .add("Green") + .add("Blue"); + + assertEquals(joiner.toString(), "[Red,Green,Blue]"); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java new file mode 100644 index 0000000000..79ed14cd99 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.string.interview; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class StringPalindromeUnitTest { + + public boolean isPalindrome(String text) { + int forward = 0; + int backward = text.length() - 1; + while (backward > forward) { + char forwardChar = text.charAt(forward++); + char backwardChar = text.charAt(backward--); + if (forwardChar != backwardChar) + return false; + } + return true; + } + + @Test + public void givenIsPalindromeMethod_whenCheckingString_thenFindIfPalindrome() { + assertThat(isPalindrome("madam")).isTrue(); + assertThat(isPalindrome("radar")).isTrue(); + assertThat(isPalindrome("level")).isTrue(); + + assertThat(isPalindrome("baeldung")).isFalse(); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java new file mode 100644 index 0000000000..bb9b45dc97 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java @@ -0,0 +1,13 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StringReverseUnitTest { + @Test + public void whenUsingInbuildMethods_thenStringReversed() { + String reversed = new StringBuilder("baeldung").reverse().toString(); + assertEquals("gnudleab", reversed); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java new file mode 100644 index 0000000000..e1cea62462 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.string.interview; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; + +public class StringSplitUnitTest { + @Test + public void givenCoreJava_whenSplittingStrings_thenSplitted() { + String expected[] = { + "john", + "peter", + "mary" + }; + + String[] splitted = "john,peter,mary".split(","); + assertArrayEquals( expected, splitted ); + } + + @Test + public void givenApacheCommons_whenSplittingStrings_thenSplitted() { + String expected[] = { + "john", + "peter", + "mary" + }; + String[] splitted = StringUtils.split("john peter mary"); + assertArrayEquals( expected, splitted ); + } + + +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java new file mode 100644 index 0000000000..aee4eedcd6 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertArrayEquals; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +public class StringToByteArrayUnitTest { + @Test + public void whenGetBytes_thenCorrect() throws UnsupportedEncodingException { + byte[] byteArray1 = "abcd".getBytes(); + byte[] byteArray2 = "efgh".getBytes(StandardCharsets.US_ASCII); + byte[] byteArray3 = "ijkl".getBytes("UTF-8"); + byte[] expected1 = new byte[] { 97, 98, 99, 100 }; + byte[] expected2 = new byte[] { 101, 102, 103, 104 }; + byte[] expected3 = new byte[] { 105, 106, 107, 108 }; + + assertArrayEquals(expected1, byteArray1); + assertArrayEquals(expected2, byteArray2); + assertArrayEquals(expected3, byteArray3); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java new file mode 100644 index 0000000000..1322d0fa82 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.string.interview; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; + +public class StringToCharArrayUnitTest { + @Test + public void whenConvertingStringToCharArray_thenConversionSuccessful() { + String beforeConvStr = "hello"; + char[] afterConvCharArr = { 'h', 'e', 'l', 'l', 'o' }; + + assertEquals(Arrays.equals(beforeConvStr.toCharArray(), afterConvCharArr), true); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java new file mode 100644 index 0000000000..a905438a84 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java @@ -0,0 +1,15 @@ +package com.baeldung.string.interview; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class StringToIntegerUnitTest { + @Test + public void givenString_whenParsingInt_shouldConvertToInt() { + String givenString = "42"; + + int result = Integer.parseInt(givenString); + + assertThat(result).isEqualTo(42); + } +} diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java new file mode 100644 index 0000000000..9a88416179 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.string.tostring; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CustomerArrayToStringUnitTest { + private static final String CUSTOMER_ARRAY_TO_STRING + = "Customer [orders=[Order [orderId=A1111, desc=Game, value=0]], getFirstName()=Rajesh, getLastName()=Bhojwani]"; + + @Test + public void givenArray_whenToString_thenCustomerDetails() { + CustomerArrayToString customer = new CustomerArrayToString(); + customer.setFirstName("Rajesh"); + customer.setLastName("Bhojwani"); + Order[] orders = new Order[1]; + orders[0] = new Order(); + orders[0].setOrderId("A1111"); + orders[0].setDesc("Game"); + orders[0].setStatus("In-Shiping"); + customer.setOrders(orders); + + assertEquals(CUSTOMER_ARRAY_TO_STRING, customer.toString()); + } + +} diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java new file mode 100644 index 0000000000..5ffb0d0e58 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.string.tostring; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CustomerComplexObjectToStringUnitTest { + private static final String CUSTOMER_COMPLEX_TO_STRING + = "Customer [order=Order [orderId=A1111, desc=Game, value=0], getFirstName()=Rajesh, getLastName()=Bhojwani]"; + + @Test + public void givenComplex_whenToString_thenCustomerDetails() { + CustomerComplexObjectToString customer = new CustomerComplexObjectToString(); + customer.setFirstName("Rajesh"); + customer.setLastName("Bhojwani"); + Order order = new Order(); + order.setOrderId("A1111"); + order.setDesc("Game"); + order.setStatus("In-Shiping"); + customer.setOrder(order); + + assertEquals(CUSTOMER_COMPLEX_TO_STRING, customer.toString()); + } + +} diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java new file mode 100644 index 0000000000..d43733bc60 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.string.tostring; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class CustomerPrimitiveToStringUnitTest { + + private static final String CUSTOMER_PRIMITIVE_TO_STRING + = "Customer [balance=110, getFirstName()=Rajesh, getLastName()=Bhojwani]"; + + @Test + public void givenPrimitive_whenToString_thenCustomerDetails() { + CustomerPrimitiveToString customer = new CustomerPrimitiveToString(); + customer.setFirstName("Rajesh"); + customer.setLastName("Bhojwani"); + customer.setBalance(110); + + assertEquals(CUSTOMER_PRIMITIVE_TO_STRING, customer.toString()); + } +} + diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java new file mode 100644 index 0000000000..e04512ff75 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.string.tostring; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class CustomerWrapperCollectionToStringUnitTest { + private static final String CUSTOMER_WRAPPER_COLLECTION_TO_STRING + = "Customer [score=8, orders=[Book, Pen], fullname=Bhojwani, Rajesh, getFirstName()=Rajesh, getLastName()=Bhojwani]"; + + @Test + public void givenWrapperCollectionStrBuffer_whenToString_thenCustomerDetails() { + CustomerWrapperCollectionToString customer = new CustomerWrapperCollectionToString(); + customer.setFirstName("Rajesh"); + customer.setLastName("Bhojwani"); + customer.setScore(8); + + List orders = new ArrayList(); + orders.add("Book"); + orders.add("Pen"); + customer.setOrders(orders); + + StringBuffer fullname = new StringBuffer(); + fullname.append(customer.getLastName()+", "+ customer.getFirstName()); + customer.setFullname(fullname); + + assertEquals(CUSTOMER_WRAPPER_COLLECTION_TO_STRING, customer.toString()); + } + +} diff --git a/javax-servlets/pom.xml b/javax-servlets/pom.xml index f00dd0ebe8..e3d8a430d9 100644 --- a/javax-servlets/pom.xml +++ b/javax-servlets/pom.xml @@ -48,7 +48,7 @@ javax.servlet.jsp javax.servlet.jsp-api - ${jsp.version} + ${javax.servlet.jsp-api.version} javax.servlet @@ -80,6 +80,7 @@ test + 4.5.3 5.0.5.RELEASE @@ -89,7 +90,5 @@ 1.3.3 2.6 4.0.1 - 1.2 - 2.3.1 diff --git a/javaxval/pom.xml b/javaxval/pom.xml index 5f2690b5b4..7ecddc0ca8 100644 --- a/javaxval/pom.xml +++ b/javaxval/pom.xml @@ -50,12 +50,12 @@ test + 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/jee-7-security/pom.xml b/jee-7-security/pom.xml index 622ca19903..5b7bb07239 100644 --- a/jee-7-security/pom.xml +++ b/jee-7-security/pom.xml @@ -4,8 +4,8 @@ 4.0.0 jee-7-security 1.0-SNAPSHOT - war jee-7-security + war JavaEE 7 Spring Security Application @@ -56,7 +56,7 @@ javax.mvc javax.mvc-api - 1.0-pr + ${javax.mvc-api.version} @@ -97,6 +97,7 @@ 2.2 1.1.2 4.2.3.RELEASE + 1.0-pr diff --git a/jee-7/README.md b/jee-7/README.md index a2493e561b..c57863651d 100644 --- a/jee-7/README.md +++ b/jee-7/README.md @@ -5,3 +5,5 @@ - [Introduction to JAX-WS](http://www.baeldung.com/jax-ws) - [A Guide to Java EE Web-Related Annotations](http://www.baeldung.com/javaee-web-annotations) - [Introduction to Testing with Arquillian](http://www.baeldung.com/arquillian) +- [Java EE 7 Batch Processing](https://www.baeldung.com/java-ee-7-batch-processing) +- [The Difference Between CDI and EJB Singleton](https://www.baeldung.com/jee-cdi-vs-ejb-singleton) diff --git a/jee-7/pom.xml b/jee-7/pom.xml index 97ed2cc51d..d389b57cd5 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -128,52 +128,52 @@ org.jboss.spec.javax.batch jboss-batch-api_1.0_spec - 1.0.0.Final + ${jboss-batch-api.version} org.jberet jberet-core - 1.0.2.Final + ${jberet.version} org.jberet jberet-support - 1.0.2.Final + ${jberet.version} org.jboss.spec.javax.transaction jboss-transaction-api_1.2_spec - 1.0.0.Final + ${jboss-transaction-api.version} org.jboss.marshalling jboss-marshalling - 1.4.2.Final + ${jboss-marshalling.version} org.jboss.weld weld-core - 2.1.1.Final + ${weld.version} org.jboss.weld.se weld-se - 2.1.1.Final + ${weld.version} org.jberet jberet-se - 1.0.2.Final + ${jberet.version} com.h2database h2 - 1.4.178 + ${h2.version} org.glassfish.jersey.containers jersey-container-jetty-servlet - 2.22.1 + ${jersey-container-jetty-servlet.version} @@ -527,12 +527,16 @@ 2.2.14 4.5 2.0.1.Final - 3.1.0 2.1.0.Final 2.8 - 1.2 2.2 20160715 + 1.0.0.Final + 1.0.2.Final + 1.0.0.Final + 1.4.2.Final + 2.1.1.Final + 2.22.1 - \ No newline at end of file + diff --git a/jee-7/src/main/java/com/baeldung/batch/understanding/CustomCheckPoint.java b/jee-7/src/main/java/com/baeldung/batch/understanding/CustomCheckPoint.java index fe6759b365..ba4eeb9da8 100644 --- a/jee-7/src/main/java/com/baeldung/batch/understanding/CustomCheckPoint.java +++ b/jee-7/src/main/java/com/baeldung/batch/understanding/CustomCheckPoint.java @@ -1,12 +1,22 @@ package com.baeldung.batch.understanding; import javax.batch.api.chunk.AbstractCheckpointAlgorithm; +import javax.batch.runtime.context.JobContext; +import javax.inject.Inject; import javax.inject.Named; @Named public class CustomCheckPoint extends AbstractCheckpointAlgorithm { + + @Inject + JobContext jobContext; + + private Integer counterRead = 0; + @Override public boolean isReadyToCheckpoint() throws Exception { - return SimpleChunkItemReader.COUNT % 5 == 0; + counterRead = (Integer)jobContext.getTransientUserData(); + System.out.println("counterRead : " + counterRead); + return counterRead % 5 == 0; } } diff --git a/jee-7/src/main/java/com/baeldung/batch/understanding/InjectSimpleBatchLet.java b/jee-7/src/main/java/com/baeldung/batch/understanding/InjectSimpleBatchLet.java index 93eb20708d..ccc052b44b 100644 --- a/jee-7/src/main/java/com/baeldung/batch/understanding/InjectSimpleBatchLet.java +++ b/jee-7/src/main/java/com/baeldung/batch/understanding/InjectSimpleBatchLet.java @@ -1,20 +1,38 @@ package com.baeldung.batch.understanding; +import java.util.Properties; +import java.util.logging.Logger; + import javax.batch.api.AbstractBatchlet; import javax.batch.api.BatchProperty; import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.context.JobContext; +import javax.batch.runtime.context.StepContext; import javax.inject.Inject; import javax.inject.Named; @Named public class InjectSimpleBatchLet extends AbstractBatchlet { + Logger logger = Logger.getLogger(InjectSimpleBatchLet.class.getName()); + @Inject @BatchProperty(name = "name") private String nameString; + @Inject + StepContext stepContext; + private Properties stepProperties; + @Inject + JobContext jobContext; + private Properties jobProperties; + @Override public String process() throws Exception { - System.out.println("Value passed in = " + nameString); + logger.info("BatchProperty : " + nameString); + stepProperties = stepContext.getProperties(); + jobProperties = jobContext.getProperties(); + logger.info("Step property : "+ stepProperties.getProperty("stepProp1")); + logger.info("job property : "+jobProperties.getProperty("jobProp1")); return BatchStatus.COMPLETED.toString(); } } diff --git a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReader.java b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReader.java index 10f81d95d0..7d66edc74c 100644 --- a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReader.java +++ b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReader.java @@ -1,20 +1,28 @@ package com.baeldung.batch.understanding; import java.io.Serializable; +import java.util.Properties; import java.util.StringTokenizer; import javax.batch.api.chunk.AbstractItemReader; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.context.JobContext; +import javax.inject.Inject; import javax.inject.Named; @Named public class SimpleChunkItemReader extends AbstractItemReader { private StringTokenizer tokens; - public static int COUNT = 0; + private Integer count=0; + + @Inject + JobContext jobContext; @Override public Integer readItem() throws Exception { if (tokens.hasMoreTokens()) { - COUNT++; + this.count++; String tempTokenize = tokens.nextToken(); + jobContext.setTransientUserData(count); return Integer.valueOf(tempTokenize); } return null; @@ -24,4 +32,5 @@ public class SimpleChunkItemReader extends AbstractItemReader { public void open(Serializable checkpoint) throws Exception { tokens = new StringTokenizer("1,2,3,4,5,6,7,8,9,10", ","); } + } diff --git a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReaderError.java b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReaderError.java index 92096d0571..f51426339f 100644 --- a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReaderError.java +++ b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkItemReaderError.java @@ -4,17 +4,22 @@ import java.io.Serializable; import java.util.StringTokenizer; import javax.batch.api.chunk.AbstractItemReader; +import javax.batch.runtime.context.JobContext; +import javax.inject.Inject; import javax.inject.Named; @Named public class SimpleChunkItemReaderError extends AbstractItemReader { + @Inject + JobContext jobContext; private StringTokenizer tokens; - public static int COUNT = 0; + private Integer count = 0; @Override public Integer readItem() throws Exception { if (tokens.hasMoreTokens()) { - COUNT++; + count++; + jobContext.setTransientUserData(count); int token = Integer.valueOf(tokens.nextToken()); if (token == 3) { throw new RuntimeException("Something happened"); diff --git a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkWriter.java b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkWriter.java index 909596766d..f21dd77b85 100644 --- a/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkWriter.java +++ b/jee-7/src/main/java/com/baeldung/batch/understanding/SimpleChunkWriter.java @@ -1,5 +1,6 @@ package com.baeldung.batch.understanding; +import java.util.ArrayList; import java.util.List; import javax.batch.api.chunk.AbstractItemWriter; @@ -7,7 +8,9 @@ import javax.inject.Named; @Named public class SimpleChunkWriter extends AbstractItemWriter { + List processed = new ArrayList<>(); @Override public void writeItems(List items) throws Exception { + items.stream().map(Integer.class::cast).forEach(this.processed::add); } } diff --git a/jee-7/src/main/java/com/baeldung/singleton/Car.java b/jee-7/src/main/java/com/baeldung/singleton/Car.java new file mode 100644 index 0000000000..0cf7281294 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/Car.java @@ -0,0 +1,28 @@ +package com.baeldung.singleton; + +public class Car { + + private String type; + private String model; + private boolean serviced = false; + + public Car(String type, String model) { + super(); + this.type = type; + this.model = model; + } + + public boolean isServiced () { + return serviced; + } + + public void setServiced(Boolean serviced) { + this.serviced = serviced; + } + + @Override + public String toString() { + return "Car [type=" + type + ", model=" + model + "]"; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java new file mode 100644 index 0000000000..b824882d5d --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java @@ -0,0 +1,23 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.enterprise.context.Dependent; + +import org.springframework.web.context.annotation.RequestScope; + +@RequestScope +public class CarServiceBean { + + private UUID id = UUID.randomUUID(); + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarService [id=" + id + "]"; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java new file mode 100644 index 0000000000..1bbffdd61e --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java @@ -0,0 +1,46 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.ejb.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class CarServiceEjbSingleton { + + private static Logger LOG = LoggerFactory.getLogger(CarServiceEjbSingleton.class); + + private UUID id = UUID.randomUUID(); + + private static int serviceQueue; + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarServiceEjbSingleton [id=" + id + "]"; + } + + public int service(Car car) { + serviceQueue++; + LOG.info("Car {} is being serviced @ CarServiceEjbSingleton - serviceQueue: {}", car, serviceQueue); + simulateService(car); + serviceQueue--; + LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue); + return serviceQueue; + } + + private void simulateService(Car car) { + try { + Thread.sleep(100); + car.setServiced(true); + } catch (InterruptedException e) { + LOG.error("CarServiceEjbSingleton::InterruptedException: {}", e); + } + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java new file mode 100644 index 0000000000..223d139346 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java @@ -0,0 +1,47 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class CarServiceSingleton { + + private static Logger LOG = LoggerFactory.getLogger(CarServiceSingleton.class); + + private UUID id = UUID.randomUUID(); + + private static int serviceQueue; + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarServiceSingleton [id=" + id + "]"; + } + + public int service(Car car) { + serviceQueue++; + LOG.info("Car {} is being serviced @ CarServiceSingleton - serviceQueue: {}", car, serviceQueue); + simulateService(car); + serviceQueue--; + LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue); + return serviceQueue; + + } + + private void simulateService(Car car) { + try { + Thread.sleep(100); + car.setServiced(true); + } catch (InterruptedException e) { + LOG.error("CarServiceSingleton::InterruptedException: {}", e); + } + } + +} diff --git a/jee-7/src/main/resources/META-INF/batch-jobs/injectionSimpleBatchLet.xml b/jee-7/src/main/resources/META-INF/batch-jobs/injectionSimpleBatchLet.xml index d152f063f6..39cb043dcf 100644 --- a/jee-7/src/main/resources/META-INF/batch-jobs/injectionSimpleBatchLet.xml +++ b/jee-7/src/main/resources/META-INF/batch-jobs/injectionSimpleBatchLet.xml @@ -1,13 +1,17 @@ - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/jee-7/src/main/resources/META-INF/batch-jobs/partitionSimpleBatchLet.xml b/jee-7/src/main/resources/META-INF/batch-jobs/partitionSimpleBatchLet.xml index 76c64ee899..49495072ea 100644 --- a/jee-7/src/main/resources/META-INF/batch-jobs/partitionSimpleBatchLet.xml +++ b/jee-7/src/main/resources/META-INF/batch-jobs/partitionSimpleBatchLet.xml @@ -4,7 +4,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd" version="1.0"> + + + + + + diff --git a/jee-7/src/test/java/com/baeldung/batch/understanding/BatchTestHelper.java b/jee-7/src/test/java/com/baeldung/batch/understanding/BatchTestHelper.java index 5060bd9b91..56269809f3 100644 --- a/jee-7/src/test/java/com/baeldung/batch/understanding/BatchTestHelper.java +++ b/jee-7/src/test/java/com/baeldung/batch/understanding/BatchTestHelper.java @@ -7,6 +7,7 @@ import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import javax.batch.runtime.JobExecution; import javax.batch.runtime.Metric; +import javax.batch.runtime.StepExecution; public class BatchTestHelper { private static final int MAX_TRIES = 40; @@ -68,6 +69,16 @@ public class BatchTestHelper { return jobExecution; } + public static long getCommitCount(StepExecution stepExecution) { + Map metricsMap = getMetricsMap(stepExecution.getMetrics()); + return metricsMap.get(Metric.MetricType.COMMIT_COUNT); + } + + public static long getProcessSkipCount(StepExecution stepExecution) { + Map metricsMap = getMetricsMap(stepExecution.getMetrics()); + return metricsMap.get(Metric.MetricType.PROCESS_SKIP_COUNT); + } + public static Map getMetricsMap(Metric[] metrics) { Map metricsMap = new HashMap<>(); for (Metric metric : metrics) { diff --git a/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointUnitTest.java b/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointUnitTest.java index a9488c5c03..dfea878a75 100644 --- a/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointUnitTest.java +++ b/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointUnitTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test; class CustomCheckPointUnitTest { @Test - public void givenChunk_whenCustomCheckPoint_thenCommitCount_3() throws Exception { + public void givenChunk_whenCustomCheckPoint_thenCommitCountIsThree() throws Exception { JobOperator jobOperator = BatchRuntime.getJobOperator(); Long executionId = jobOperator.start("customCheckPoint", new Properties()); JobExecution jobExecution = jobOperator.getJobExecution(executionId); @@ -23,9 +23,10 @@ class CustomCheckPointUnitTest { for (StepExecution stepExecution : jobOperator.getStepExecutions(executionId)) { if (stepExecution.getStepName() .equals("firstChunkStep")) { - Map metricsMap = BatchTestHelper.getMetricsMap(stepExecution.getMetrics()); - assertEquals(3L, metricsMap.get(Metric.MetricType.COMMIT_COUNT) - .longValue()); + jobOperator.getStepExecutions(executionId) + .stream() + .map(BatchTestHelper::getCommitCount) + .forEach(count -> assertEquals(3L, count.longValue())); } } assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); diff --git a/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetUnitTest.java b/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetUnitTest.java index 485c997cc6..ade492b1b9 100644 --- a/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetUnitTest.java +++ b/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetUnitTest.java @@ -1,18 +1,11 @@ package com.baeldung.batch.understanding; import static org.junit.jupiter.api.Assertions.*; - -import java.util.List; -import java.util.Map; import java.util.Properties; - import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import javax.batch.runtime.JobExecution; -import javax.batch.runtime.Metric; -import javax.batch.runtime.StepExecution; - import org.junit.jupiter.api.Test; class SimpleBatchLetUnitTest { diff --git a/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkUnitTest.java b/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkUnitTest.java index 0f6d068888..ded31b6345 100644 --- a/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkUnitTest.java +++ b/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkUnitTest.java @@ -1,5 +1,6 @@ package com.baeldung.batch.understanding; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.*; @@ -23,7 +24,6 @@ class SimpleErrorChunkUnitTest { Long executionId = jobOperator.start("simpleErrorChunk", new Properties()); JobExecution jobExecution = jobOperator.getJobExecution(executionId); jobExecution = BatchTestHelper.keepTestFailed(jobExecution); - System.out.println(jobExecution.getBatchStatus()); assertEquals(jobExecution.getBatchStatus(), BatchStatus.FAILED); } @@ -37,10 +37,10 @@ class SimpleErrorChunkUnitTest { for (StepExecution stepExecution : stepExecutions) { if (stepExecution.getStepName() .equals("errorStep")) { - Map metricsMap = BatchTestHelper.getMetricsMap(stepExecution.getMetrics()); - long skipCount = metricsMap.get(MetricType.PROCESS_SKIP_COUNT) - .longValue(); - assertTrue("Skip count=" + skipCount, skipCount == 1l || skipCount == 2l); + jobOperator.getStepExecutions(executionId) + .stream() + .map(BatchTestHelper::getProcessSkipCount) + .forEach(skipCount -> assertEquals(1L, skipCount.longValue())); } } assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); diff --git a/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java new file mode 100644 index 0000000000..60a647f32c --- /dev/null +++ b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java @@ -0,0 +1,109 @@ +package com.baeldung.singleton; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.EJB; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.CDI; +import javax.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RunWith(Arquillian.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CarServiceIntegrationTest { + + public static final Logger LOG = LoggerFactory.getLogger(CarServiceIntegrationTest.class); + + @Deployment + public static JavaArchive createDeployment() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(CarServiceBean.class, CarServiceSingleton.class, CarServiceEjbSingleton.class, Car.class) + .addAsResource("META-INF/persistence.xml") + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Inject + private CarServiceBean carServiceBean; + + @Inject + private CarServiceSingleton carServiceSingleton; + + @EJB + private CarServiceEjbSingleton carServiceEjbSingleton; + + @Test + public void givenASingleton_whenGetBeanIsCalledTwice_thenTheSameInstanceIsReturned() { + CarServiceSingleton one = getBean(CarServiceSingleton.class); + CarServiceSingleton two = getBean(CarServiceSingleton.class); + assertTrue(one == two); + } + + @Test + public void givenAPojo_whenGetBeanIsCalledTwice_thenDifferentInstancesAreReturned() { + CarServiceBean one = getBean(CarServiceBean.class); + CarServiceBean two = getBean(CarServiceBean.class); + assertTrue(one != two); + } + + @SuppressWarnings("unchecked") + private T getBean(Class beanClass) { + BeanManager bm = CDI.current().getBeanManager(); + Bean bean = (Bean) bm.getBeans(beanClass).iterator().next(); + CreationalContext ctx = bm.createCreationalContext(bean); + return (T) bm.getReference(bean, beanClass, ctx); + } + + @Test + public void givenCDI_whenConcurrentAccess_thenLockingIsNotProvided() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceSingleton.service(car); + assertTrue(serviceQueue < 10); + } + }).start(); + } + return; + } + + @Test + public void givenEJB_whenConcurrentAccess_thenLockingIsProvided() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceEjbSingleton.service(car); + assertEquals(0, serviceQueue); + } + }).start(); + } + return; + } + +} \ No newline at end of file diff --git a/jersey/README.md b/jersey/README.md index 1dd871b3e8..126dc542ba 100644 --- a/jersey/README.md +++ b/jersey/README.md @@ -3,3 +3,4 @@ - [Bean Validation in Jersey](https://www.baeldung.com/jersey-bean-validation) - [Set a Response Body in JAX-RS](https://www.baeldung.com/jax-rs-response) - [Exploring the Jersey Test Framework](https://www.baeldung.com/jersey-test) +- [Explore Jersey Request Parameters](https://www.baeldung.com/jersey-request-parameters) diff --git a/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java b/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java new file mode 100644 index 0000000000..0f60a20b92 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java @@ -0,0 +1,46 @@ +package com.baeldung.jersey.server; + +import javax.ws.rs.FormParam; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PathParam; + +public class ItemParam { + + @HeaderParam("headerParam") + private String shopKey; + + @PathParam("pathParam") + private String itemId; + + @FormParam("formParam") + private String price; + + public String getShopKey() { + return shopKey; + } + + public void setShopKey(String shopKey) { + this.shopKey = shopKey; + } + + public String getItemId() { + return itemId; + } + + public void setItemId(String itemId) { + this.itemId = itemId; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + @Override + public String toString() { + return "ItemParam{shopKey='" + shopKey + ", itemId='" + itemId + ", price='" + price + '}'; + } +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/Items.java b/jersey/src/main/java/com/baeldung/jersey/server/Items.java new file mode 100644 index 0000000000..c24e6820f5 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/Items.java @@ -0,0 +1,49 @@ +package com.baeldung.jersey.server; + +import javax.ws.rs.*; + +@Path("items") +public class Items { + + @GET + @Path("/cookie") + public String readCookieParam(@CookieParam("cookieParamToRead") String cookieParamToRead) { + return "Cookie parameter value is [" + cookieParamToRead + "]"; + } + + @GET + @Path("/header") + public String readHeaderParam(@HeaderParam("headerParamToRead") String headerParamToRead) { + return "Header parameter value is [" + headerParamToRead + "]"; + } + + @GET + @Path("/path/{pathParamToRead}") + public String readPathParam(@PathParam("pathParamToRead") String pathParamToRead) { + return "Path parameter value is [" + pathParamToRead + "]"; + } + + @GET + @Path("/query") + public String readQueryParam(@QueryParam("queryParamToRead") String queryParamToRead) { + return "Query parameter value is [" + queryParamToRead + "]"; + } + + @POST + @Path("/form") + public String readFormParam(@FormParam("formParamToRead") String formParamToRead) { + return "Form parameter value is [" + formParamToRead + "]"; + } + + @GET + @Path("/matrix") + public String readMatrixParam(@MatrixParam("matrixParamToRead") String matrixParamToRead) { + return "Matrix parameter value is [" + matrixParamToRead + "]"; + } + + @POST + @Path("/bean/{pathParam}") + public String readBeanParam(@BeanParam ItemParam itemParam) { + return itemParam.toString(); + } +} \ No newline at end of file diff --git a/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java index 4afa086858..1d75508c6d 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java @@ -7,12 +7,13 @@ import java.util.logging.Logger; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.server.ResourceConfig; import com.baeldung.jersey.server.config.ViewApplicationConfig; public class EmbeddedHttpServer { - private static final URI BASE_URI = URI.create("http://localhost:8082/"); + public static final URI BASE_URI = URI.create("http://localhost:8082/"); public static void main(String[] args) { try { @@ -32,4 +33,9 @@ public class EmbeddedHttpServer { } } + + public static HttpServer startServer() { + final ResourceConfig rc = new ResourceConfig().packages("com.baeldung.jersey.server"); + return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI.toString()), rc); + } } diff --git a/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java b/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java new file mode 100644 index 0000000000..df85e26b76 --- /dev/null +++ b/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.jersey.server; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; + +import org.glassfish.grizzly.http.server.HttpServer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.jersey.server.http.EmbeddedHttpServer; + +public class ItemsUnitTest { + + private HttpServer server; + private WebTarget target; + + @Before + public void setUp() throws Exception { + server = EmbeddedHttpServer.startServer(); + target = ClientBuilder.newClient().target(EmbeddedHttpServer.BASE_URI.toString()); + } + + @After + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void givenCookieParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "1"; + String responseText = target.path("items/cookie").request().cookie("cookieParamToRead", paramValue).get(String.class); + assertEquals("Cookie parameter value is [" + paramValue + "]", responseText); + } + + @Test + public void givenHeaderParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "2"; + String responseText = target.path("items/header").request().header("headerParamToRead", paramValue).get(String.class); + assertEquals("Header parameter value is [" + paramValue + "]", responseText); + } + + @Test + public void givenPathParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "3"; + String responseText = target.path("items/path/" + paramValue).request().get(String.class); + assertEquals("Path parameter value is [" + paramValue + "]", responseText); + } +} diff --git a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java index 376c8c1e75..f7bb0df1ed 100644 --- a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java +++ b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java @@ -26,6 +26,7 @@ public class FruitResourceIntegrationTest extends JerseyTest { protected Application configure() { enable(TestProperties.LOG_TRAFFIC); enable(TestProperties.DUMP_ENTITY); + forceSet(TestProperties.CONTAINER_PORT, "0"); ViewApplicationConfig config = new ViewApplicationConfig(); config.register(FruitExceptionMapper.class); diff --git a/jgroups/pom.xml b/jgroups/pom.xml index 34bdd59919..e95fe2be3c 100644 --- a/jgroups/pom.xml +++ b/jgroups/pom.xml @@ -4,9 +4,9 @@ 4.0.0 jgroups 0.1-SNAPSHOT - jar jgroups Reliable Messaging with JGroups Tutorial + jar com.baeldung diff --git a/jhipster-5/README.md b/jhipster-5/README.md new file mode 100644 index 0000000000..0537f5b1a5 --- /dev/null +++ b/jhipster-5/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Creating New APIs and Views in JHipster](https://www.baeldung.com/jhipster-new-apis-and-views) 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/.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/.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 0000000000..01e6799737 Binary files /dev/null and b/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.jar differ diff --git a/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.properties b/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..cd0d451ccd --- /dev/null +++ b/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/jhipster-5/bookstore-monolith/.prettierignore b/jhipster-5/bookstore-monolith/.prettierignore new file mode 100644 index 0000000000..151fcf7916 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.prettierignore @@ -0,0 +1,3 @@ +node_modules +target +package-lock.json diff --git a/jhipster-5/bookstore-monolith/.prettierrc b/jhipster-5/bookstore-monolith/.prettierrc new file mode 100644 index 0000000000..6fd4aa1267 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.prettierrc @@ -0,0 +1,12 @@ +# Prettier configuration + +printWidth: 140 +singleQuote: true +tabWidth: 4 +useTabs: false + +# js and ts rules: +arrowParens: avoid + +# jsx and tsx rules: +jsxBracketSameLine: false diff --git a/jhipster-5/bookstore-monolith/.yo-rc.json b/jhipster-5/bookstore-monolith/.yo-rc.json new file mode 100644 index 0000000000..d852aeeddc --- /dev/null +++ b/jhipster-5/bookstore-monolith/.yo-rc.json @@ -0,0 +1,34 @@ +{ + "generator-jhipster": { + "promptValues": { + "packageName": "com.baeldung.jhipster5" + }, + "jhipsterVersion": "5.8.2", + "applicationType": "monolith", + "baseName": "Bookstore", + "packageName": "com.baeldung.jhipster5", + "packageFolder": "com/baeldung/jhipster5", + "serverPort": "8080", + "authenticationType": "jwt", + "cacheProvider": "no", + "websocket": false, + "databaseType": "sql", + "devDatabaseType": "h2Memory", + "prodDatabaseType": "mysql", + "searchEngine": false, + "messageBroker": false, + "serviceDiscoveryType": false, + "buildTool": "maven", + "enableSwaggerCodegen": false, + "jwtSecretKey": "NDJmOTVlZjI2NzhlZDRjNmVkNTM1NDE2NjkyNDljZDJiNzBlMjI5YmZjMjY3MzdjZmZlMjI3NjE4OTRkNzc5MWYzNDNlYWMzYmJjOWRmMjc5ZWQyZTZmOWZkOTMxZWZhNWE1MTVmM2U2NjFmYjhlNDc2Y2Q3NzliMGY0YzFkNmI=", + "clientFramework": "angularX", + "useSass": true, + "clientPackageManager": "npm", + "testFrameworks": [], + "jhiPrefix": "jhi", + "entitySuffix": "", + "dtoSuffix": "DTO", + "otherModules": [], + "enableTranslation": false + } +} diff --git a/jhipster-5/bookstore-monolith/README.md b/jhipster-5/bookstore-monolith/README.md new file mode 100644 index 0000000000..1387b82163 --- /dev/null +++ b/jhipster-5/bookstore-monolith/README.md @@ -0,0 +1,179 @@ +# Bookstore + +This application was generated using JHipster 5.8.2, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v5.8.2](https://www.jhipster.tech/documentation-archive/v5.8.2). + +## Development + +Before you can build this project, you must install and configure the following dependencies on your machine: + +1. [Node.js][]: We use Node to run a development web server and build the project. + Depending on your system, you can install Node either from source or as a pre-packaged bundle. + +After installing Node, you should be able to run the following command to install development tools. +You will only need to run this command when dependencies change in [package.json](package.json). + + npm install + +We use npm scripts and [Webpack][] as our build system. + +Run the following commands in two separate terminals to create a blissful development experience where your browser +auto-refreshes when files change on your hard drive. + + ./mvnw + npm start + +Npm is also used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by +specifying a newer version in [package.json](package.json). You can also run `npm update` and `npm install` to manage dependencies. +Add the `help` flag on any command to see how you can use it. For example, `npm help update`. + +The `npm run` command will list all of the scripts available to run for this project. + +### Service workers + +Service workers are commented by default, to enable them please uncomment the following code. + +- The service worker registering script in index.html + +```html + +``` + +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..60fc1acf92 --- /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 + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + 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/ + + + + 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 + *

+ * 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. + *

+ * 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..f07944271e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java @@ -0,0 +1,122 @@ +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/books/purchase/**").authenticated() + .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/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/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/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/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/BookService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java new file mode 100644 index 0000000000..6422d1a424 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java @@ -0,0 +1,50 @@ +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); + + /** + * 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/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/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/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/impl/BookServiceImpl.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java new file mode 100644 index 0000000000..23cd59584c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java @@ -0,0 +1,109 @@ +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 com.baeldung.jhipster5.web.rest.errors.BadRequestAlertException; +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); + } + + @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/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/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/BookResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java new file mode 100644 index 0000000000..0360ea05ed --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java @@ -0,0 +1,118 @@ +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(); + } + + @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/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/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 new file mode 100644 index 0000000000..e045ee0100 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml @@ -0,0 +1,11 @@ + + + + + + + + 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 0000000000..364fad7435 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/resources/config/tls/keystore.p12 differ 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/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..4a3c20e841 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html @@ -0,0 +1,49 @@ +
+
+
+

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..6b84c0ba73 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts @@ -0,0 +1,36 @@ +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', + templateUrl: './book-detail.component.html' +}) +export class BookDetailComponent implements OnInit { + book: IBook; + + constructor(protected activatedRoute: ActivatedRoute, protected bookService: BookService) {} + + ngOnInit() { + this.activatedRoute.data.subscribe(({ book }) => { + this.book = book; + }); + } + + 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-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..bff511f7e6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts @@ -0,0 +1,81 @@ +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))); + } + + 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 + .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 new file mode 100644 index 0000000000..fba1f55ef7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts @@ -0,0 +1,19 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +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 */ + ]) + ], + 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..e58d234c22 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html @@ -0,0 +1,145 @@ + 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/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/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 0000000000..8133068921 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-192.png differ 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 0000000000..b4739ec3e4 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-256.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-384.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-384.png new file mode 100644 index 0000000000..0280f27e8b Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-384.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-512.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-512.png new file mode 100644 index 0000000000..326141b927 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-512.png differ 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 0000000000..dd2643c15d Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-192.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-256.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-256.png new file mode 100644 index 0000000000..2c5352683a Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-256.png differ 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 0000000000..f930681c12 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-384.png differ 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 0000000000..9110dc8fe4 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-512.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2.svg b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2.svg new file mode 100755 index 0000000000..1747933833 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2.svg @@ -0,0 +1,841 @@ + + + +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 0000000000..2699ab4473 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-192.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-256.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-256.png new file mode 100644 index 0000000000..3a5903e19e Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-256.png differ 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 0000000000..da964fcb2e Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-384.png differ 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 0000000000..6337f5effb Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-512.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3.svg b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3.svg new file mode 100755 index 0000000000..6b9e056662 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 0000000000..35b91257fc Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-192.png differ 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 0000000000..098fd8fb05 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-256.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-384.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-384.png new file mode 100644 index 0000000000..b770045754 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-384.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-512.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-512.png new file mode 100644 index 0000000000..58b28b9c48 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-512.png differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/logo-jhipster.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/logo-jhipster.png new file mode 100755 index 0000000000..5d31c2f84d Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/logo-jhipster.png differ 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 0000000000..4179874f53 Binary files /dev/null and b/jhipster-5/bookstore-monolith/src/main/webapp/favicon.ico differ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/index.html b/jhipster-5/bookstore-monolith/src/main/webapp/index.html new file mode 100644 index 0000000000..a2fd4df265 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/index.html @@ -0,0 +1,108 @@ + + + + + + + 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/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/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/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(); + }); + }); +}); 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 0000000000..d8eb48da05 Binary files /dev/null and b/jhipster-5/bookstore-monolith/webpack/logo-jhipster.png differ diff --git a/jhipster-5/bookstore-monolith/webpack/utils.js b/jhipster-5/bookstore-monolith/webpack/utils.js new file mode 100644 index 0000000000..2fce772341 --- /dev/null +++ b/jhipster-5/bookstore-monolith/webpack/utils.js @@ -0,0 +1,44 @@ +const fs = require('fs'); +const path = require('path'); + +module.exports = { + parseVersion, + root, + isExternalLib +}; + +const parseString = require('xml2js').parseString; +// return the version number from `pom.xml` file +function parseVersion() { + let version = null; + const pomXml = fs.readFileSync('pom.xml', 'utf8'); + parseString(pomXml, (err, result) => { + 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' +}); 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 + + + diff --git a/jhipster/README.md b/jhipster/README.md index f3655f8ec1..289bfac754 100644 --- a/jhipster/README.md +++ b/jhipster/README.md @@ -2,3 +2,5 @@ - [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) diff --git a/jhipster/jhipster-microservice/car-app/pom.xml b/jhipster/jhipster-microservice/car-app/pom.xml index b05979b9c5..86d94d0a44 100644 --- a/jhipster/jhipster-microservice/car-app/pom.xml +++ b/jhipster/jhipster-microservice/car-app/pom.xml @@ -7,7 +7,6 @@ com.baeldung.jhipster 1.0.0-SNAPSHOT - com.car.app car-app war @@ -898,4 +897,5 @@ + diff --git a/jhipster/jhipster-microservice/dealer-app/pom.xml b/jhipster/jhipster-microservice/dealer-app/pom.xml index 803a0f62e6..3051399ae6 100644 --- a/jhipster/jhipster-microservice/dealer-app/pom.xml +++ b/jhipster/jhipster-microservice/dealer-app/pom.xml @@ -7,7 +7,6 @@ com.baeldung.jhipster 1.0.0-SNAPSHOT - com.dealer.app dealer-app war diff --git a/jhipster/jhipster-microservice/gateway-app/pom.xml b/jhipster/jhipster-microservice/gateway-app/pom.xml index ed0c929027..4e2c19ed2d 100644 --- a/jhipster/jhipster-microservice/gateway-app/pom.xml +++ b/jhipster/jhipster-microservice/gateway-app/pom.xml @@ -7,7 +7,6 @@ com.baeldung.jhipster 1.0.0-SNAPSHOT - com.gateway gateway-app war 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 diff --git a/jhipster/jhipster-uaa/gateway/pom.xml b/jhipster/jhipster-uaa/gateway/pom.xml index 52f84e4006..0f815bedad 100644 --- a/jhipster/jhipster-uaa/gateway/pom.xml +++ b/jhipster/jhipster-uaa/gateway/pom.xml @@ -1,12 +1,11 @@ 4.0.0 - com.baeldung.jhipster.gateway gateway 0.0.1-SNAPSHOT - war Gateway + war @@ -14,87 +13,6 @@ - - - 3.0.0 - 1.8 - 2.12.6 - v8.12.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.0.25 - - 2.0.5.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 - 3.1.0 - 2.22.0 - 3.2.2 - 0.9.11 - 1.6 - 0.8.2 - 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - src/main/java/**/* - squid:S4684 - ${project.testresult.directory}/coverage/jacoco/jacoco.exec - jacoco - ${project.testresult.directory}/jest/TESTS-results-sonar.xml - ${project.testresult.directory}/lcov.info - ${project.basedir}/src/main/ - ${project.testresult.directory}/surefire-reports - ${project.basedir}/src/test/ - - - - @@ -1092,4 +1010,85 @@ + + + + 3.0.0 + 1.8 + 2.12.6 + v8.12.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.0.25 + + 2.0.5.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 + 3.1.0 + 2.22.0 + 3.2.2 + 0.9.11 + 1.6 + 0.8.2 + 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + src/main/java/**/* + squid:S4684 + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + jacoco + ${project.testresult.directory}/jest/TESTS-results-sonar.xml + ${project.testresult.directory}/lcov.info + ${project.basedir}/src/main/ + ${project.testresult.directory}/surefire-reports + ${project.basedir}/src/test/ + + + diff --git a/jhipster/jhipster-uaa/pom.xml b/jhipster/jhipster-uaa/pom.xml new file mode 100644 index 0000000000..a59b19d1fd --- /dev/null +++ b/jhipster/jhipster-uaa/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + jhipster-uaa + jhipster-uaa + pom + + + jhipster + com.baeldung.jhipster + 1.0.0-SNAPSHOT + + + + uaa + gateway + quotes + + + diff --git a/jhipster/jhipster-uaa/quotes/pom.xml b/jhipster/jhipster-uaa/quotes/pom.xml index 9984f009ff..81ab23471f 100644 --- a/jhipster/jhipster-uaa/quotes/pom.xml +++ b/jhipster/jhipster-uaa/quotes/pom.xml @@ -1,12 +1,11 @@ 4.0.0 - com.baeldung.jhipster.quotes quotes 0.0.1-SNAPSHOT - war Quotes + war @@ -14,85 +13,6 @@ - - - 3.0.0 - 1.8 - 2.12.6 - v8.12.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.0.25 - - 2.0.5.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 - 3.1.0 - 2.22.0 - 3.2.2 - 0.9.11 - 0.8.2 - 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - 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}/surefire-reports - ${project.basedir}/src/test/ - - - - @@ -912,4 +832,83 @@ + + + + 3.0.0 + 1.8 + 2.12.6 + v8.12.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.0.25 + + 2.0.5.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 + 3.1.0 + 2.22.0 + 3.2.2 + 0.9.11 + 0.8.2 + 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + 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}/surefire-reports + ${project.basedir}/src/test/ + + + diff --git a/jhipster/jhipster-uaa/uaa/pom.xml b/jhipster/jhipster-uaa/uaa/pom.xml index 9c4783747a..2c4dd9d0f0 100644 --- a/jhipster/jhipster-uaa/uaa/pom.xml +++ b/jhipster/jhipster-uaa/uaa/pom.xml @@ -1,12 +1,11 @@ 4.0.0 - com.baeldung.jhipster.uaa uaa 0.0.1-SNAPSHOT - war Uaa + war @@ -14,85 +13,6 @@ - - - 3.0.0 - 1.8 - 2.12.6 - v8.12.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.0.25 - - 2.0.5.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 - 3.1.0 - 2.22.0 - 3.2.2 - 0.9.11 - 0.8.2 - 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - 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}/surefire-reports - ${project.basedir}/src/test/ - - - - @@ -912,4 +832,84 @@ + + + + 3.0.0 + 1.8 + 2.12.6 + v8.12.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.0.25 + + 2.0.5.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 + 3.1.0 + 2.22.0 + 3.2.2 + 0.9.11 + 0.8.2 + 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,S4684,UndocumentedApi,BoldAndItalicTagsCheck + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + 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}/surefire-reports + ${project.basedir}/src/test/ + + + + diff --git a/jhipster/pom.xml b/jhipster/pom.xml index 2bf7bcb233..c50aac0c7a 100644 --- a/jhipster/pom.xml +++ b/jhipster/pom.xml @@ -5,8 +5,8 @@ com.baeldung.jhipster jhipster 1.0.0-SNAPSHOT - pom JHipster + pom parent-boot-1 @@ -15,9 +15,17 @@ ../parent-boot-1 + + + org.hibernate + hibernate-java8 + + + jhipster-monolithic jhipster-microservice + jhipster-uaa diff --git a/jib/pom.xml b/jib/pom.xml index e71250f157..2341fcca0c 100644 --- a/jib/pom.xml +++ b/jib/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 jib 0.1-SNAPSHOT @@ -18,11 +18,7 @@ spring-boot-starter-web - - - 1.8 - - + @@ -32,7 +28,7 @@ com.google.cloud.tools jib-maven-plugin - 0.9.10 + ${jib-maven-plugin.version} registry.hub.docker.com/baeldungjib/jib-spring-boot-app @@ -42,16 +38,7 @@ - - - spring-releases - https://repo.spring.io/libs-release - - - - - spring-releases - https://repo.spring.io/libs-release - - + + 0.9.10 + 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: diff --git a/jjwt/pom.xml b/jjwt/pom.xml index 6bf9f4426a..2d03543293 100644 --- a/jjwt/pom.xml +++ b/jjwt/pom.xml @@ -5,8 +5,8 @@ io.jsonwebtoken jjwt 0.0.1-SNAPSHOT - jar jjwt + jar Exercising the JJWT diff --git a/jmeter/pom.xml b/jmeter/pom.xml index 943b75e03b..514546987d 100644 --- a/jmeter/pom.xml +++ b/jmeter/pom.xml @@ -4,9 +4,9 @@ 4.0.0 jmeter 0.0.1-SNAPSHOT - jar jmeter Intro to Performance testing using JMeter + jar parent-boot-1 diff --git a/jmh/pom.xml b/jmh/pom.xml index 1e01809fe6..70a0a398d4 100644 --- a/jmh/pom.xml +++ b/jmh/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung jmh - jar 1.0-SNAPSHOT jmh + jar http://maven.apache.org 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) diff --git a/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java b/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java new file mode 100644 index 0000000000..1bd12f8bb3 --- /dev/null +++ b/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java @@ -0,0 +1,21 @@ +package com.baeldung.jooby; + +import static io.restassured.RestAssured.get; +import static org.hamcrest.Matchers.equalTo; + +import org.jooby.test.JoobyRule; +import org.junit.ClassRule; +import org.junit.Test; + +public class AppLiveTest { + + @ClassRule + public static JoobyRule app = new JoobyRule(new App()); + + @Test + public void given_defaultUrl_expect_fixedString() { + get("/").then().assertThat().body(equalTo("Hello World!")).statusCode(200) + .contentType("text/html;charset=UTF-8"); + } + +} diff --git a/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java b/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java index ab7388f5f4..9bca30e2c1 100644 --- a/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java +++ b/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java @@ -1,25 +1,12 @@ package com.baeldung.jooby; -import static io.restassured.RestAssured.get; -import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; -import org.jooby.test.JoobyRule; import org.jooby.test.MockRouter; -import org.junit.ClassRule; import org.junit.Test; public class AppUnitTest { - @ClassRule - public static JoobyRule app = new JoobyRule(new App()); - - @Test - public void given_defaultUrl_expect_fixedString() { - get("/").then().assertThat().body(equalTo("Hello World!")).statusCode(200) - .contentType("text/html;charset=UTF-8"); - } - @Test public void given_defaultUrl_with_mockrouter_expect_fixedString() throws Throwable { String result = new MockRouter(new App()).get("/"); 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) diff --git a/jsf/pom.xml b/jsf/pom.xml index fc6d4a0ee2..19f1265250 100644 --- a/jsf/pom.xml +++ b/jsf/pom.xml @@ -67,7 +67,7 @@ javax.servlet javax.servlet-api provided - ${javax.servlet.version} + ${javax.servlet-api.version} @@ -99,11 +99,6 @@ 2.2.14 3.0.0 - - 3.1.0 - - 1.2 - 2.6 diff --git a/json/README.md b/json/README.md index 2e253a4ae9..7ef4cc9b01 100644 --- a/json/README.md +++ b/json/README.md @@ -11,3 +11,5 @@ - [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) +- [Escape JSON String in Java](https://www.baeldung.com/java-json-escaping) diff --git a/json/pom.xml b/json/pom.xml index fce2d26db5..c76625a6fa 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -32,17 +32,17 @@ org.json json - 20171018 + ${json.version} com.google.code.gson gson - 2.8.5 + ${gson.version} com.fasterxml.jackson.core jackson-databind - 2.9.7 + ${jackson.version} javax.json.bind @@ -52,14 +52,14 @@ junit junit - 4.12 + ${junit.version} test org.glassfish javax.json - 1.1.2 + ${javax.version} org.eclipse @@ -73,6 +73,12 @@ ${commons-collections4.version} test + + org.assertj + assertj-core + ${assertj-core.version} + test + @@ -81,6 +87,10 @@ 1.0 4.1 1.0.1 + 20171018 + 2.8.5 + 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; + } + +} diff --git a/jta/pom.xml b/jta/pom.xml index 4754c1872b..b7e39c66e1 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -7,22 +7,15 @@ 1.0-SNAPSHOT jta jar - 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 - - UTF-8 - UTF-8 - 1.8 - - org.springframework.boot @@ -46,7 +39,7 @@ org.hsqldb hsqldb - 2.4.1 + ${hsqldb.version} @@ -86,4 +79,11 @@ + + + UTF-8 + UTF-8 + 2.4.1 + 2.0.4.RELEASE + diff --git a/jws/pom.xml b/jws/pom.xml index 2c89b687f8..6bc790e7ee 100644 --- a/jws/pom.xml +++ b/jws/pom.xml @@ -34,6 +34,7 @@ + ${project.artifactId} org.apache.maven.plugins @@ -78,7 +79,6 @@ - ${project.artifactId} diff --git a/kotlin-libraries-2/.gitignore b/kotlin-libraries-2/.gitignore new file mode 100644 index 0000000000..0c017e8f8c --- /dev/null +++ b/kotlin-libraries-2/.gitignore @@ -0,0 +1,14 @@ +/bin/ + +#ignore gradle +.gradle/ + + +#ignore build and generated files +build/ +node/ +out/ + +#ignore installed node modules and package lock file +node_modules/ +package-lock.json diff --git a/kotlin-libraries-2/README.md b/kotlin-libraries-2/README.md new file mode 100644 index 0000000000..0b9f238d51 --- /dev/null +++ b/kotlin-libraries-2/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Jackson Support for Kotlin](https://www.baeldung.com/jackson-kotlin) +- [Introduction to RxKotlin](https://www.baeldung.com/rxkotlin) diff --git a/kotlin-libraries-2/pom.xml b/kotlin-libraries-2/pom.xml new file mode 100644 index 0000000000..14ac61a093 --- /dev/null +++ b/kotlin-libraries-2/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + kotlin-libraries-2 + kotlin-libraries-2 + jar + + + com.baeldung + parent-kotlin + 1.0.0-SNAPSHOT + ../parent-kotlin + + + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + io.reactivex.rxjava2 + rxkotlin + 2.3.0 + + + junit + junit + test + + + + + + + diff --git a/kotlin-libraries-2/resources/logback.xml b/kotlin-libraries-2/resources/logback.xml new file mode 100644 index 0000000000..9452207268 --- /dev/null +++ b/kotlin-libraries-2/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt new file mode 100644 index 0000000000..4ff47ea987 --- /dev/null +++ b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt @@ -0,0 +1,8 @@ +package com.baeldung.kotlin.jackson + +import com.fasterxml.jackson.annotation.* + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +data class Book(var title: String, @JsonProperty("author") var authorName: String) { + var genres: List? = emptyList() +} \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt new file mode 100644 index 0000000000..445b6013d5 --- /dev/null +++ b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt @@ -0,0 +1,3 @@ +package com.baeldung.kotlin.jackson + +data class Movie(var name: String, var studio: String, var rating: Float? = 1f) \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt new file mode 100644 index 0000000000..84171d9019 --- /dev/null +++ b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt @@ -0,0 +1,114 @@ +package com.baeldung.kotlin.jackson + +import org.junit.Test +import kotlin.test.assertTrue +import kotlin.test.assertFalse +import kotlin.test.assertEquals +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule + +class JacksonUnitTest { + //val mapper = jacksonObjectMapper() + val mapper = ObjectMapper().registerModule(KotlinModule()) + + + @Test + fun whenSerializeMovie_thenSuccess() { + val movie = Movie("Endgame", "Marvel", 9.2f) + val serialized = mapper.writeValueAsString(movie) + + val json = """{"name":"Endgame","studio":"Marvel","rating":9.2}""" + assertEquals(serialized, json) + } + + @Test + fun whenDeserializeMovie_thenSuccess() { + val json = """{"name":"Endgame","studio":"Marvel","rating":9.2}""" + // val movie: Movie = mapper.readValue(json) + val movie = mapper.readValue(json) + + assertEquals(movie.name, "Endgame") + assertEquals(movie.studio, "Marvel") + assertEquals(movie.rating, 9.2f) + } + + @Test + fun whenDeserializeMovieWithMissingValue_thenUseDefaultValue() { + val json = """{"name":"Endgame","studio":"Marvel"}""" + val movie: Movie = mapper.readValue(json) + + assertEquals(movie.name, "Endgame") + assertEquals(movie.studio, "Marvel") + assertEquals(movie.rating, 1f) + } + + @Test + fun whenSerializeMap_thenSuccess() { + val map = mapOf(1 to "one", 2 to "two") + val serialized = mapper.writeValueAsString(map) + + val json = """{"1":"one","2":"two"}""" + assertEquals(serialized, json) + } + + @Test + fun whenDeserializeMap_thenSuccess() { + val json = """{"1":"one","2":"two"}""" + val aMap: Map = mapper.readValue(json) + + assertEquals(aMap[1], "one") + assertEquals(aMap[2], "two") + } + + @Test + fun whenSerializeList_thenSuccess() { + val movie1 = Movie("Endgame", "Marvel", 9.2f) + val movie2 = Movie("Shazam", "Warner Bros", 7.6f) + val movieList = listOf(movie1, movie2) + val serialized = mapper.writeValueAsString(movieList) + + val json = """[{"name":"Endgame","studio":"Marvel","rating":9.2},{"name":"Shazam","studio":"Warner Bros","rating":7.6}]""" + assertEquals(serialized, json) + } + + @Test + fun whenDeserializeList_thenSuccess() { + val json = """[{"name":"Endgame","studio":"Marvel","rating":9.2},{"name":"Shazam","studio":"Warner Bros","rating":7.6}]""" + val movieList: List = mapper.readValue(json) + + val movie1 = Movie("Endgame", "Marvel", 9.2f) + val movie2 = Movie("Shazam", "Warner Bros", 7.6f) + assertTrue(movieList.contains(movie1)) + assertTrue(movieList.contains(movie2)) + } + + @Test + fun whenSerializeBook_thenSuccess() { + val book = Book("Oliver Twist", "Charles Dickens") + val serialized = mapper.writeValueAsString(book) + + val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" + assertEquals(serialized, json) + } + + @Test + fun whenDeserializeBook_thenSuccess() { + val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" + val book: Book = mapper.readValue(json) + + assertEquals(book.title, "Oliver Twist") + assertEquals(book.authorName, "Charles Dickens") + } + + @Test + fun givenJsonInclude_whenSerializeBook_thenEmptyFieldExcluded() { + val book = Book("Oliver Twist", "Charles Dickens") + val serialized = mapper.writeValueAsString(book) + + val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" + assertEquals(serialized, json) + } + +} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt new file mode 100644 index 0000000000..979ed3f809 --- /dev/null +++ b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt @@ -0,0 +1,157 @@ +package com.baeldung.kotlin.rxkotlin + +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.functions.BiFunction +import io.reactivex.rxkotlin.* +import io.reactivex.subjects.PublishSubject +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse + +class RxKotlinTest { + + @Test + fun whenBooleanArrayToObserver_thenBooleanObserver() { + val observable = listOf(true, false, false).toObservable() + observable.test().assertValues(true, false, false) + } + + @Test + fun whenBooleanArrayToFlowable_thenBooleanFlowable() { + val flowable = listOf(true, false, false).toFlowable() + flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) + } + + @Test + fun whenIntArrayToObserver_thenIntObserver() { + val observable = listOf(1, 1, 2, 3).toObservable() + observable.test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenIntArrayToFlowable_thenIntFlowable() { + val flowable = listOf(1, 1, 2, 3).toFlowable() + flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) + } + + @Test + fun whenObservablePairToMap_thenSingleNoDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMap() + assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) + } + + @Test + fun whenObservablePairToMap_thenSingleWithDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMultimap() + assertEquals( + mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), + map.blockingGet()) + } + + @Test + fun whenMergeAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.mergeAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenConcatAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.concatAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenSwitchLatest_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.switchLatest() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenMergeAllMaybes_thenObservable() { + val subject = PublishSubject.create>() + val observable = subject.mergeAllMaybes() + val testObserver = observable.test() + subject.onNext(Maybe.just(1)) + subject.onNext(Maybe.just(2)) + subject.onNext(Maybe.empty()) + testObserver.assertValues(1, 2) + subject.onNext(Maybe.error(Exception(""))) + subject.onNext(Maybe.just(3)) + testObserver.assertValues(1, 2).assertError(Exception::class.java) + } + + @Test + fun whenMerge_thenStream() { + val observables = mutableListOf(Observable.just("first", "second")) + val observable = observables.merge() + observables.add(Observable.just("third", "fourth")) + observables.add(Observable.error(Exception("e"))) + observables.add(Observable.just("fifth")) + + observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) + } + + @Test + fun whenMergeDelayError_thenStream() { + val observables = mutableListOf>(Observable.error(Exception("e1"))) + val observable = observables.mergeDelayError() + observables.add(Observable.just("1", "2")) + observables.add(Observable.error(Exception("e2"))) + observables.add(Observable.just("3")) + + observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) + } + + @Test + fun whenCast_thenUniformType() { + val observable = Observable.just(1, 1, 2, 3) + observable.cast().test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenOfType_thenFilter() { + val observable = Observable.just(1, "and", 2, "and") + observable.ofType().test().assertValues(1, 2) + } + + @Test + fun whenFunction_thenCompletable() { + var value = 0 + val completable = { value = 3 }.toCompletable() + assertFalse(completable.test().isCancelled) + assertEquals(3, value) + } + + @Test + fun whenHelper_thenMoreIdiomaticKotlin() { + val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } + zipWith.subscribeBy(onNext = { println(it) }) + val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } + zip.subscribeBy(onNext = { println(it) }) + val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) + zipOrig.subscribeBy(onNext = { println(it) }) + } +} diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md index d1ef77aa46..94359193b6 100644 --- a/kotlin-libraries/README.md +++ b/kotlin-libraries/README.md @@ -5,7 +5,10 @@ - [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) - [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek) - [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson) -- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor) - [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) - [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates) - [Introduction to Arrow in Kotlin](https://www.baeldung.com/kotlin-arrow) +- [Kotlin with Ktor](https://www.baeldung.com/kotlin-ktor) +- [REST API With Kotlin and Kovert](https://www.baeldung.com/kotlin-kovert) +- [MockK: A Mocking Library for Kotlin](https://www.baeldung.com/kotlin-mockk) +- [Kotlin Immutable Collections](https://www.baeldung.com/kotlin-immutable-collections) \ No newline at end of file diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle index b244df34b0..db23a438a0 100644 --- a/kotlin-libraries/build.gradle +++ b/kotlin-libraries/build.gradle @@ -7,6 +7,7 @@ version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '1.2.41' ext.ktor_version = '0.9.2' + ext.khttp_version = '0.1.0' repositories { mavenCentral() @@ -47,11 +48,15 @@ dependencies { compile "io.ktor:ktor-server-netty:$ktor_version" compile "ch.qos.logback:logback-classic:1.2.1" compile "io.ktor:ktor-gson:$ktor_version" + compile "khttp:khttp:$khttp_version" testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'org.jetbrains.spek', name: 'spek-api', version: '1.1.5' + testCompile group: 'org.jetbrains.spek', name: 'spek-subject-extension', version: '1.1.5' + testCompile group: 'org.jetbrains.spek', name: 'spek-junit-platform-engine', version: '1.1.5' implementation 'com.beust:klaxon:3.0.1' - } + task runServer(type: JavaExec) { main = 'APIServer' classpath = sourceSets.main.runtimeClasspath -} \ No newline at end of file +} diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index ae77a9aa2d..b75c77f358 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 + @@ -95,9 +103,79 @@ 0.7.3 + + uy.kohesive.kovert + kovert-vertx + [1.5.0,1.6.0) + + + nl.komponents.kovenant + kovenant + + + + + nl.komponents.kovenant + kovenant + 3.3.0 + pom + + + + + junit + junit + ${junit.version} + test + + + + com.google.guava + guava + 27.1-jre + + + + org.jetbrains.kotlinx + 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 + + + + io.reactivex.rxjava2 + rxkotlin + 2.3.0 + + 4.12 1.5.0 4.1.0 3.0.4 @@ -108,6 +186,7 @@ 3.10.0 1.4.197 0.10.4 + 1.9.3 - \ No newline at end of file + diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt diff --git a/core-kotlin/src/main/resources/kovert.conf b/kotlin-libraries/src/main/resources/kovert.conf similarity index 100% rename from core-kotlin/src/main/resources/kovert.conf rename to kotlin-libraries/src/main/resources/kovert.conf 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 diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt new file mode 100644 index 0000000000..979ed3f809 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt @@ -0,0 +1,157 @@ +package com.baeldung.kotlin.rxkotlin + +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.functions.BiFunction +import io.reactivex.rxkotlin.* +import io.reactivex.subjects.PublishSubject +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse + +class RxKotlinTest { + + @Test + fun whenBooleanArrayToObserver_thenBooleanObserver() { + val observable = listOf(true, false, false).toObservable() + observable.test().assertValues(true, false, false) + } + + @Test + fun whenBooleanArrayToFlowable_thenBooleanFlowable() { + val flowable = listOf(true, false, false).toFlowable() + flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) + } + + @Test + fun whenIntArrayToObserver_thenIntObserver() { + val observable = listOf(1, 1, 2, 3).toObservable() + observable.test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenIntArrayToFlowable_thenIntFlowable() { + val flowable = listOf(1, 1, 2, 3).toFlowable() + flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) + } + + @Test + fun whenObservablePairToMap_thenSingleNoDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMap() + assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) + } + + @Test + fun whenObservablePairToMap_thenSingleWithDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMultimap() + assertEquals( + mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), + map.blockingGet()) + } + + @Test + fun whenMergeAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.mergeAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenConcatAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.concatAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenSwitchLatest_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.switchLatest() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenMergeAllMaybes_thenObservable() { + val subject = PublishSubject.create>() + val observable = subject.mergeAllMaybes() + val testObserver = observable.test() + subject.onNext(Maybe.just(1)) + subject.onNext(Maybe.just(2)) + subject.onNext(Maybe.empty()) + testObserver.assertValues(1, 2) + subject.onNext(Maybe.error(Exception(""))) + subject.onNext(Maybe.just(3)) + testObserver.assertValues(1, 2).assertError(Exception::class.java) + } + + @Test + fun whenMerge_thenStream() { + val observables = mutableListOf(Observable.just("first", "second")) + val observable = observables.merge() + observables.add(Observable.just("third", "fourth")) + observables.add(Observable.error(Exception("e"))) + observables.add(Observable.just("fifth")) + + observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) + } + + @Test + fun whenMergeDelayError_thenStream() { + val observables = mutableListOf>(Observable.error(Exception("e1"))) + val observable = observables.mergeDelayError() + observables.add(Observable.just("1", "2")) + observables.add(Observable.error(Exception("e2"))) + observables.add(Observable.just("3")) + + observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) + } + + @Test + fun whenCast_thenUniformType() { + val observable = Observable.just(1, 1, 2, 3) + observable.cast().test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenOfType_thenFilter() { + val observable = Observable.just(1, "and", 2, "and") + observable.ofType().test().assertValues(1, 2) + } + + @Test + fun whenFunction_thenCompletable() { + var value = 0 + val completable = { value = 3 }.toCompletable() + assertFalse(completable.test().isCancelled) + assertEquals(3, value) + } + + @Test + fun whenHelper_thenMoreIdiomaticKotlin() { + val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } + zipWith.subscribeBy(onNext = { println(it) }) + val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } + zip.subscribeBy(onNext = { println(it) }) + val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) + zipOrig.subscribeBy(onNext = { println(it) }) + } +} 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 diff --git a/kotlin-quasar/README.md b/kotlin-quasar/README.md new file mode 100644 index 0000000000..b3b84e0446 --- /dev/null +++ b/kotlin-quasar/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Introduction to Quasar in Kotlin](https://www.baeldung.com/kotlin-quasar) diff --git a/kotlin-quasar/pom.xml b/kotlin-quasar/pom.xml new file mode 100644 index 0000000000..a3e5a1ec25 --- /dev/null +++ b/kotlin-quasar/pom.xml @@ -0,0 +1,143 @@ + + + 4.0.0 + com.baeldung + kotlin-quasar + 1.0.0-SNAPSHOT + kotlin-quasar + jar + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + co.paralleluniverse + quasar-core + ${quasar.version} + + + co.paralleluniverse + quasar-actors + ${quasar.version} + + + co.paralleluniverse + quasar-reactive-streams + ${quasar.version} + + + co.paralleluniverse + quasar-kotlin + ${quasar.version} + + + junit + junit + 4.12 + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + + src/main/kotlin + src/test/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + maven-dependency-plugin + 3.1.1 + + + getClasspathFilenames + + properties + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + -Dco.paralleluniverse.fibers.verifyInstrumentation=true + -javaagent:${co.paralleluniverse:quasar-core:jar} + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + target/classes + echo + + -javaagent:${co.paralleluniverse:quasar-core:jar} + -classpath + com.baeldung.quasar.QuasarHelloWorldKt + + + + + + + + 0.8.0 + 1.3.31 + 1.7.21 + 1.1.7 + + diff --git a/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt b/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt new file mode 100644 index 0000000000..9bf01ecb09 --- /dev/null +++ b/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt @@ -0,0 +1,19 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Fiber +import co.paralleluniverse.strands.SuspendableRunnable + + +/** + * Entrypoint into the application + */ +fun main(args: Array) { + class Runnable : SuspendableRunnable { + override fun run() { + println("Hello") + } + } + val result = Fiber(Runnable()).start() + result.join() + println("World") +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt new file mode 100644 index 0000000000..b4d0288a64 --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt @@ -0,0 +1,157 @@ +package com.baeldung.quasar + +import co.paralleluniverse.actors.Actor +import co.paralleluniverse.actors.ActorRef +import co.paralleluniverse.actors.behaviors.* +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.strands.SuspendableCallable +import org.junit.Test +import org.slf4j.LoggerFactory +import java.lang.Exception + +class ActorsBehaviorTest { + companion object { + private val LOG = LoggerFactory.getLogger(ActorsBehaviorTest::class.java) + } + + @Test + fun requestReplyHelper() { + data class TestMessage(val input: Int) : RequestMessage() + + val actor = object : Actor("requestReplyActor", null) { + @Suspendable + override fun doRun(): Void? { + while (true) { + val msg = receive() + LOG.info("Processing message: {}", msg) + + RequestReplyHelper.reply(msg, msg.input * 100) + } + } + } + + val actorRef = actor.spawn() + + val result = RequestReplyHelper.call(actorRef, TestMessage(50)) + LOG.info("Received reply: {}", result) + } + + @Test + fun server() { + val actor = ServerActor(object : AbstractServerHandler() { + @Suspendable + override fun handleCall(from: ActorRef<*>?, id: Any?, m: Int?): String { + LOG.info("Called with message: {} from {} with ID {}", m, from, id) + return m.toString() ?: "None" + } + + @Suspendable + override fun handleCast(from: ActorRef<*>?, id: Any?, m: Float?) { + LOG.info("Cast message: {} from {} with ID {}", m, from, id) + } + }) + + val server = actor.spawn() + + LOG.info("Call result: {}", server.call(5)) + server.cast(2.5f) + + server.shutdown() + } + + interface Summer { + fun sum(a: Int, b: Int) : Int + } + + @Test + fun proxyServer() { + val actor = ProxyServerActor(false, object : Summer { + @Synchronized + override fun sum(a: Int, b: Int): Int { + Exception().printStackTrace() + LOG.info("Adding together {} and {}", a, b) + return a + b + } + }) + + val summerActor = actor.spawn() + + val result = (summerActor as Summer).sum(1, 2) + LOG.info("Result: {}", result) + + summerActor.shutdown() + } + + @Test + fun eventSource() { + val actor = EventSourceActor() + val eventSource = actor.spawn() + + eventSource.addHandler { msg -> + LOG.info("Sent message: {}", msg) + } + + val name = "Outside Value" + eventSource.addHandler { msg -> + LOG.info("Also Sent message: {} {}", msg, name) + } + + eventSource.send("Hello") + + eventSource.shutdown() + } + + @Test + fun finiteStateMachine() { + val actor = object : FiniteStateMachineActor() { + @Suspendable + override fun initialState(): SuspendableCallable> { + LOG.info("Starting") + return SuspendableCallable { lockedState() } + } + + @Suspendable + fun lockedState() : SuspendableCallable> { + return receive {msg -> + when (msg) { + "PUSH" -> { + LOG.info("Still locked") + lockedState() + } + "COIN" -> { + LOG.info("Unlocking...") + unlockedState() + } + else -> TERMINATE + } + } + } + + @Suspendable + fun unlockedState() : SuspendableCallable> { + return receive {msg -> + when (msg) { + "PUSH" -> { + LOG.info("Locking") + lockedState() + } + "COIN" -> { + LOG.info("Unlocked") + unlockedState() + } + else -> TERMINATE + } + } + } + } + + val actorRef = actor.spawn() + + listOf("PUSH", "COIN", "COIN", "PUSH", "PUSH").forEach { + LOG.info(it) + actorRef.sendSync(it) + } + + actorRef.shutdown() + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt new file mode 100644 index 0000000000..819a149af3 --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt @@ -0,0 +1,298 @@ +package com.baeldung.quasar + +import co.paralleluniverse.actors.* +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.strands.channels.Channels +import org.junit.Assert +import org.junit.Test +import org.slf4j.LoggerFactory +import java.util.concurrent.TimeUnit + +class ActorsTest { + companion object { + private val LOG = LoggerFactory.getLogger(ActorsTest::class.java) + } + + @Test + fun createNoopActor() { + val actor = object : Actor("noopActor", MailboxConfig(5, Channels.OverflowPolicy.THROW)) { + @Suspendable + override fun doRun(): String { + return "Hello" + } + } + + actor.spawn() + + println("Noop Actor: ${actor.get()}") + } + + @Test + fun registerActor() { + val actor = object : Actor("registerActor", null) { + @Suspendable + override fun doRun(): String { + return "Hello" + } + } + + val actorRef = actor.spawn() + actor.register() + + val retrievedRef = ActorRegistry.getActor>("registerActor") + + Assert.assertEquals(actorRef, retrievedRef) + actor.join() + } + + @Test + fun registerActorNewName() { + val actor = object : Actor(null, null) { + @Suspendable + override fun doRun(): String { + return "Hello" + } + } + + val actorRef = actor.spawn() + actor.register("renamedActor") + + val retrievedRef = ActorRegistry.getActor>("renamedActor") + + Assert.assertEquals(actorRef, retrievedRef) + actor.join() + } + + @Test + fun retrieveUnknownActor() { + val retrievedRef = ActorRegistry.getActor>("unknownActor", 1, TimeUnit.SECONDS) + + Assert.assertNull(retrievedRef) + } + + @Test + fun createSimpleActor() { + val actor = object : Actor("simpleActor", null) { + @Suspendable + override fun doRun(): Void? { + val msg = receive() + LOG.info("SimpleActor Received Message: {}", msg) + + return null + } + } + + val actorRef = actor.spawn() + + actorRef.send(1) + + actor.join() + } + + @Test + fun createLoopingActor() { + val actor = object : Actor("loopingActor", null) { + @Suspendable + override fun doRun(): Void? { + while (true) { + val msg = receive() + + if (msg > 0) { + LOG.info("LoopingActor Received Message: {}", msg) + } else { + break + } + } + + return null + } + } + + val actorRef = actor.spawn() + + actorRef.send(3) + actorRef.send(2) + actorRef.send(1) + actorRef.send(0) + + actor.join() + } + + @Test + fun actorBacklog() { + val actor = object : Actor("backlogActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { + @Suspendable + override fun doRun(): String { + TimeUnit.MILLISECONDS.sleep(500); + LOG.info("Backlog Actor Received: {}", receive()) + + try { + receive() + } catch (e: Throwable) { + LOG.info("==== Exception throws by receive() ====") + e.printStackTrace() + } + + return "No Exception" + } + } + + val actorRef = actor.spawn() + + actorRef.send(1) + actorRef.send(2) + + try { + LOG.info("Backlog Actor: {}", actor.get()) + } catch (e: Exception) { + // Expected + LOG.info("==== Exception throws by get() ====") + e.printStackTrace() + } + } + + @Test + fun actorBacklogTrySend() { + val actor = object : Actor("backlogTrySendActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { + @Suspendable + override fun doRun(): String { + TimeUnit.MILLISECONDS.sleep(500); + LOG.info("Backlog TrySend Actor Received: {}", receive()) + + return "No Exception" + } + } + + val actorRef = actor.spawn() + + LOG.info("Backlog TrySend 1: {}", actorRef.trySend(1)) + LOG.info("Backlog TrySend 1: {}", actorRef.trySend(2)) + + actor.join() + } + + @Test + fun actorTimeoutReceive() { + val actor = object : Actor("TimeoutReceiveActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { + @Suspendable + override fun doRun(): String { + LOG.info("Timeout Actor Received: {}", receive(500, TimeUnit.MILLISECONDS)) + + return "Finished" + } + } + + val actorRef = actor.spawn() + + TimeUnit.MILLISECONDS.sleep(300) + actorRef.trySend(1) + + actor.join() + } + + + @Test + fun actorNonBlockingReceive() { + val actor = object : Actor("NonBlockingReceiveActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { + @Suspendable + override fun doRun(): String { + LOG.info("NonBlocking Actor Received #1: {}", tryReceive()) + TimeUnit.MILLISECONDS.sleep(500) + LOG.info("NonBlocking Actor Received #2: {}", tryReceive()) + + return "Finished" + } + } + + val actorRef = actor.spawn() + + TimeUnit.MILLISECONDS.sleep(300) + actorRef.trySend(1) + + actor.join() + } + + @Test + fun evenActor() { + val actor = object : Actor("EvenActor", null) { + @Suspendable + override fun filterMessage(m: Any?): Int? { + return when (m) { + is Int -> { + if (m % 2 == 0) { + m * 10 + } else { + null + } + } + else -> super.filterMessage(m) + } + } + + @Suspendable + override fun doRun(): Void? { + while (true) { + val msg = receive() + + if (msg > 0) { + LOG.info("EvenActor Received Message: {}", msg) + } else { + break + } + } + + return null + } + } + + val actorRef = actor.spawn() + + actorRef.send(3) + actorRef.send(2) + actorRef.send(1) + actorRef.send(0) + + actor.join() + } + + @Test + fun watchingActors() { + val watched = object : Actor("WatchedActor", null) { + @Suspendable + override fun doRun(): Void? { + LOG.info("WatchedActor Starting") + receive(500, TimeUnit.MILLISECONDS) + LOG.info("WatchedActor Finishing") + return null + } + } + + val watcher = object : Actor("WatcherActor", null) { + @Suspendable + override fun doRun(): Void? { + LOG.info("WatcherActor Listening") + try { + LOG.info("WatcherActor received Message: {}", receive(2, TimeUnit.SECONDS)) + } catch (e: Exception) { + LOG.info("WatcherActor Received Exception", e) + } + return null + } + + @Suspendable + override fun handleLifecycleMessage(m: LifecycleMessage?): Int? { + LOG.info("WatcherActor Received Lifecycle Message: {}", m) + return super.handleLifecycleMessage(m) + } + } + + val watcherRef = watcher.spawn() + TimeUnit.MILLISECONDS.sleep(200) + + val watchedRef = watched.spawn() + watcher.link(watchedRef) + + watched.join() + watcher.join() + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt new file mode 100644 index 0000000000..b51943446e --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt @@ -0,0 +1,155 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.kotlin.fiber +import co.paralleluniverse.strands.channels.Channels +import co.paralleluniverse.strands.channels.Selector +import com.google.common.base.Function +import org.junit.Test + +class ChannelsTest { + @Test + fun createChannel() { + Channels.newChannel(0, // The size of the channel buffer + Channels.OverflowPolicy.BLOCK, // The policy for when the buffer is full + true, // Whether we should optimize for a single message producer + true) // Whether we should optimize for a single message consumer + } + + @Test + fun blockOnMessage() { + val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + + fiber @Suspendable { + while (!channel.isClosed) { + val message = channel.receive() + println("Received: $message") + } + println("Stopped receiving messages") + } + + channel.send("Hello") + channel.send("World") + + channel.close() + } + + @Test + fun selectReceiveChannels() { + val channel1 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + val channel2 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + + fiber @Suspendable { + while (!channel1.isClosed && !channel2.isClosed) { + val received = Selector.select(Selector.receive(channel1), Selector.receive(channel2)) + + println("Received: $received") + } + } + + fiber @Suspendable { + for (i in 0..10) { + channel1.send("Channel 1: $i") + } + } + + fiber @Suspendable { + for (i in 0..10) { + channel2.send("Channel 2: $i") + } + } + } + + @Test + fun selectSendChannels() { + val channel1 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + val channel2 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + + fiber @Suspendable { + for (i in 0..10) { + Selector.select( + Selector.send(channel1, "Channel 1: $i"), + Selector.send(channel2, "Channel 2: $i") + ) + } + } + + fiber @Suspendable { + while (!channel1.isClosed) { + val msg = channel1.receive() + println("Read: $msg") + } + } + + fiber @Suspendable { + while (!channel2.isClosed) { + val msg = channel2.receive() + println("Read: $msg") + } + } + } + + @Test + fun tickerChannel() { + val channel = Channels.newChannel(3, Channels.OverflowPolicy.DISPLACE) + + for (i in 0..10) { + val tickerConsumer = Channels.newTickerConsumerFor(channel) + fiber @Suspendable { + while (!tickerConsumer.isClosed) { + val message = tickerConsumer.receive() + println("Received on $i: $message") + } + println("Stopped receiving messages on $i") + } + } + + for (i in 0..50) { + channel.send("Message $i") + } + + channel.close() + } + + + @Test + fun transformOnSend() { + val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + + fiber @Suspendable { + while (!channel.isClosed) { + val message = channel.receive() + println("Received: $message") + } + println("Stopped receiving messages") + } + + val transformOnSend = Channels.mapSend(channel, Function { msg: String? -> msg?.toUpperCase() }) + + transformOnSend.send("Hello") + transformOnSend.send("World") + + channel.close() + } + + @Test + fun transformOnReceive() { + val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) + + val transformOnReceive = Channels.map(channel, Function { msg: String? -> msg?.reversed() }) + + fiber @Suspendable { + while (!transformOnReceive.isClosed) { + val message = transformOnReceive.receive() + println("Received: $message") + } + println("Stopped receiving messages") + } + + + channel.send("Hello") + channel.send("World") + + channel.close() + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt new file mode 100644 index 0000000000..3f73af3917 --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt @@ -0,0 +1,35 @@ +package com.baeldung.quasar + +import co.paralleluniverse.strands.dataflow.Val +import co.paralleluniverse.strands.dataflow.Var +import org.junit.Assert +import org.junit.Test +import java.util.concurrent.TimeUnit + +class DataflowTest { + @Test + fun testValVar() { + val a = Var() + val b = Val() + + val c = Var { a.get() + b.get() } + val d = Var { a.get() * b.get() } + + // (a*b) - (a+b) + val initialResult = Val { d.get() - c.get() } + val currentResult = Var { d.get() - c.get() } + + a.set(2) + b.set(4) + + Assert.assertEquals(2, initialResult.get()) + Assert.assertEquals(2, currentResult.get()) + + a.set(3) + + TimeUnit.SECONDS.sleep(1) + + Assert.assertEquals(2, initialResult.get()) + Assert.assertEquals(5, currentResult.get()) + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt new file mode 100644 index 0000000000..d4ea04820d --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt @@ -0,0 +1,53 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Fiber +import co.paralleluniverse.fibers.FiberAsync +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.kotlin.fiber +import co.paralleluniverse.strands.Strand +import org.junit.Assert +import org.junit.Test +import java.math.BigDecimal +import java.util.concurrent.TimeUnit + +interface PiCallback { + fun success(result: BigDecimal) + fun failure(error: Exception) +} + +fun computePi(callback: PiCallback) { + println("Starting calculations") + TimeUnit.SECONDS.sleep(2) + println("Finished calculations") + callback.success(BigDecimal("3.14")) +} + +class PiAsync : PiCallback, FiberAsync() { + override fun success(result: BigDecimal) { + asyncCompleted(result) + } + + override fun failure(error: Exception) { + asyncFailed(error) + } + + override fun requestAsync() { + computePi(this) + } +} + +class PiAsyncTest { + @Test + fun testPi() { + val result = fiber @Suspendable { + val pi = PiAsync() + println("Waiting to get PI on: " + Fiber.currentFiber().name) + val result = pi.run() + println("Got PI") + + result + }.get() + + Assert.assertEquals(BigDecimal("3.14"), result) + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt new file mode 100644 index 0000000000..83e06bf7d6 --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt @@ -0,0 +1,135 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.kotlin.fiber +import co.paralleluniverse.strands.channels.Channels +import co.paralleluniverse.strands.channels.Topic +import co.paralleluniverse.strands.channels.reactivestreams.ReactiveStreams +import org.junit.Test +import org.reactivestreams.Subscriber +import org.reactivestreams.Subscription +import org.slf4j.LoggerFactory +import java.util.concurrent.TimeUnit + +class ReactiveStreamsTest { + companion object { + private val LOG = LoggerFactory.getLogger(ReactiveStreamsTest::class.java) + } + + @Test + fun publisher() { + val inputChannel = Channels.newChannel(1); + + val publisher = ReactiveStreams.toPublisher(inputChannel) + publisher.subscribe(object : Subscriber { + @Suspendable + override fun onComplete() { + LOG.info("onComplete") + } + + @Suspendable + override fun onSubscribe(s: Subscription) { + LOG.info("onSubscribe: {}", s) + s.request(2) + } + + @Suspendable + override fun onNext(t: String?) { + LOG.info("onNext: {}", t) + } + + @Suspendable + override fun onError(t: Throwable?) { + LOG.info("onError: {}", t) + } + }) + + inputChannel.send("Hello") + inputChannel.send("World") + + TimeUnit.SECONDS.sleep(1) + + inputChannel.close() + } + + @Test + fun publisherTopic() { + val inputTopic = Topic() + + val publisher = ReactiveStreams.toPublisher(inputTopic) + publisher.subscribe(object : Subscriber { + @Suspendable + override fun onComplete() { + LOG.info("onComplete 1") + } + + @Suspendable + override fun onSubscribe(s: Subscription) { + LOG.info("onSubscribe 1: {}", s) + s.request(2) + } + + @Suspendable + override fun onNext(t: String?) { + LOG.info("onNext 1: {}", t) + } + + @Suspendable + override fun onError(t: Throwable?) { + LOG.info("onError 1: {}", t) + } + }) + publisher.subscribe(object : Subscriber { + @Suspendable + override fun onComplete() { + LOG.info("onComplete 2") + } + + @Suspendable + override fun onSubscribe(s: Subscription) { + LOG.info("onSubscribe 2: {}", s) + s.request(2) + } + + @Suspendable + override fun onNext(t: String?) { + LOG.info("onNext 2: {}", t) + } + + @Suspendable + override fun onError(t: Throwable?) { + LOG.info("onError 2: {}", t) + } + }) + + inputTopic.send("Hello") + inputTopic.send("World") + + TimeUnit.SECONDS.sleep(1) + + inputTopic.close() + } + + @Test + fun subscribe() { + val inputChannel = Channels.newChannel(10); + val publisher = ReactiveStreams.toPublisher(inputChannel) + + val channel = ReactiveStreams.subscribe(10, Channels.OverflowPolicy.THROW, publisher) + + fiber @Suspendable { + while (!channel.isClosed) { + val message = channel.receive() + LOG.info("Received: {}", message) + } + LOG.info("Stopped receiving messages") + } + + inputChannel.send("Hello") + inputChannel.send("World") + + TimeUnit.SECONDS.sleep(1) + + inputChannel.close() + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt new file mode 100644 index 0000000000..9b139dd686 --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt @@ -0,0 +1,48 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Fiber +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.kotlin.fiber +import co.paralleluniverse.strands.SuspendableCallable +import org.junit.Assert +import org.junit.Test +import java.util.concurrent.TimeUnit + + +class SuspendableCallableTest { + @Test + fun createFiber() { + class Callable : SuspendableCallable { + override fun run(): String { + println("Inside Fiber") + return "Hello" + } + } + val result = Fiber(Callable()).start() + + Assert.assertEquals("Hello", result.get()) + } + + @Test + fun createFiberLambda() { + val lambda: (() -> String) = { + println("Inside Fiber Lambda") + "Hello" + } + val result = Fiber(lambda) + result.start() + + Assert.assertEquals("Hello", result.get()) + } + + @Test + fun createFiberDsl() { + val result = fiber @Suspendable { + TimeUnit.SECONDS.sleep(5) + println("Inside Fiber DSL") + "Hello" + } + + Assert.assertEquals("Hello", result.get()) + } +} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt new file mode 100644 index 0000000000..ba4cef8f4c --- /dev/null +++ b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt @@ -0,0 +1,47 @@ +package com.baeldung.quasar + +import co.paralleluniverse.fibers.Fiber +import co.paralleluniverse.fibers.Suspendable +import co.paralleluniverse.kotlin.fiber +import co.paralleluniverse.strands.SuspendableRunnable +import org.junit.Test +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException + + +class SuspensableRunnableTest { + @Test + fun createFiber() { + class Runnable : SuspendableRunnable { + override fun run() { + println("Inside Fiber") + } + } + val result = Fiber(Runnable()).start() + result.join() + } + + @Test + fun createFiberLambda() { + val result = Fiber { + println("Inside Fiber Lambda") + } + result.start() + result.join() + } + + @Test + fun createFiberDsl() { + fiber @Suspendable { + println("Inside Fiber DSL") + }.join() + } + + @Test(expected = TimeoutException::class) + fun fiberTimeout() { + fiber @Suspendable { + TimeUnit.SECONDS.sleep(5) + println("Inside Fiber DSL") + }.join(2, TimeUnit.SECONDS) + } +} diff --git a/libraries-2/README.md b/libraries-2/README.md new file mode 100644 index 0000000000..1b042ac3c5 --- /dev/null +++ b/libraries-2/README.md @@ -0,0 +1,10 @@ + +### Relevant Articles: + +- [A Guide to jBPM with Java](https://www.baeldung.com/jbpm-java) +- [Guide to Classgraph Library](https://www.baeldung.com/classgraph) +- [Create a Java Command Line Program with Picocli](https://www.baeldung.com/java-picocli-create-command-line-program) +- [Guide to Java Parallel Collectors Library](https://www.baeldung.com/java-parallel-collectors) +- [Templating with Handlebars](https://www.baeldung.com/handlebars) +- [A Guide to Crawler4j](https://www.baeldung.com/crawler4j) +- [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response) diff --git a/libraries-2/pom.xml b/libraries-2/pom.xml new file mode 100644 index 0000000000..ff73888b69 --- /dev/null +++ b/libraries-2/pom.xml @@ -0,0 +1,169 @@ + + + 4.0.0 + libraries2 + libraries2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + jboss-public-repository-group + JBoss Public Repository Group + http://repository.jboss.org/nexus/content/groups/public/ + + true + never + + + true + daily + + + + + + + org.mapdb + mapdb + ${mapdb.version} + + + com.pivovarit + parallel-collectors + ${parallel-collectors.version} + + + org.assertj + assertj-core + ${assertj.version} + + + io.github.classgraph + classgraph + ${classgraph.version} + + + org.jbpm + jbpm-test + ${jbpm.version} + + + info.picocli + picocli + ${picocli.version} + + + org.ejml + ejml-all + ${ejml.version} + + + org.nd4j + nd4j-native + ${nd4j.version} + + + org.la4j + la4j + ${la4j.version} + + + colt + colt + ${colt.version} + + + org.springframework.boot + spring-boot-starter + ${spring-boot-starter.version} + + + net.openhft + chronicle-map + ${chronicle.map.version} + + + com.sun.java + tools + + + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.google.code.gson + gson + ${gson.version} + + + com.squareup.okhttp3 + mockwebserver + ${mockwebserver.version} + test + + + edu.uci.ics + crawler4j + ${crawler4j.version} + + + com.github.jknack + handlebars + ${handlebars.version} + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + org.apache.mesos + mesos + ${mesos.library.version} + + + + + 3.0.7 + 3.6.2 + 4.8.28 + 6.0.0.Final + 3.9.6 + 3.17.2 + 4.4.0 + 2.1.4.RELEASE + 0.38 + 1.0.0-beta4 + 1.2.0 + 0.6.0 + 1.19 + 0.28.3 + 1.1.0 + 3.14.2 + 2.8.5 + 3.14.2 + 4.1.2 + + diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/CrawlerStatistics.java b/libraries-2/src/main/java/com/baeldung/crawler4j/CrawlerStatistics.java new file mode 100644 index 0000000000..e3237a2755 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/CrawlerStatistics.java @@ -0,0 +1,22 @@ +package com.baeldung.crawler4j; + +public class CrawlerStatistics { + private int processedPageCount = 0; + private int totalLinksCount = 0; + + public void incrementProcessedPageCount() { + processedPageCount++; + } + + public void incrementTotalLinksCount(int linksCount) { + totalLinksCount += linksCount; + } + + public int getProcessedPageCount() { + return processedPageCount; + } + + public int getTotalLinksCount() { + return totalLinksCount; + } +} diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawler.java b/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawler.java new file mode 100644 index 0000000000..b77e1e075f --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawler.java @@ -0,0 +1,48 @@ +package com.baeldung.crawler4j; + +import java.util.Set; +import java.util.regex.Pattern; + +import edu.uci.ics.crawler4j.crawler.Page; +import edu.uci.ics.crawler4j.crawler.WebCrawler; +import edu.uci.ics.crawler4j.parser.HtmlParseData; +import edu.uci.ics.crawler4j.url.WebURL; + +public class HtmlCrawler extends WebCrawler { + + private final static Pattern EXCLUSIONS = Pattern.compile(".*(\\.(css|js|xml|gif|jpg|png|mp3|mp4|zip|gz|pdf))$"); + + private CrawlerStatistics stats; + + public HtmlCrawler(CrawlerStatistics stats) { + this.stats = stats; + } + + @Override + public boolean shouldVisit(Page referringPage, WebURL url) { + String urlString = url.getURL().toLowerCase(); + return !EXCLUSIONS.matcher(urlString).matches() + && urlString.startsWith("https://www.baeldung.com/"); + } + + @Override + public void visit(Page page) { + String url = page.getWebURL().getURL(); + stats.incrementProcessedPageCount(); + + if (page.getParseData() instanceof HtmlParseData) { + HtmlParseData htmlParseData = (HtmlParseData) page.getParseData(); + String title = htmlParseData.getTitle(); + String text = htmlParseData.getText(); + String html = htmlParseData.getHtml(); + Set links = htmlParseData.getOutgoingUrls(); + stats.incrementTotalLinksCount(links.size()); + + System.out.printf("Page with title '%s' %n", title); + System.out.printf(" Text length: %d %n", text.length()); + System.out.printf(" HTML length: %d %n", html.length()); + System.out.printf(" %d outbound links %n", links.size()); + } + } + +} diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawlerController.java b/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawlerController.java new file mode 100644 index 0000000000..82c1c6bdd7 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/HtmlCrawlerController.java @@ -0,0 +1,36 @@ +package com.baeldung.crawler4j; + +import java.io.File; + +import edu.uci.ics.crawler4j.crawler.CrawlConfig; +import edu.uci.ics.crawler4j.crawler.CrawlController; +import edu.uci.ics.crawler4j.fetcher.PageFetcher; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtConfig; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtServer; + +public class HtmlCrawlerController { + + public static void main(String[] args) throws Exception { + File crawlStorage = new File("src/test/resources/crawler4j"); + CrawlConfig config = new CrawlConfig(); + config.setCrawlStorageFolder(crawlStorage.getAbsolutePath()); + config.setMaxDepthOfCrawling(2); + + int numCrawlers = 12; + + PageFetcher pageFetcher = new PageFetcher(config); + RobotstxtConfig robotstxtConfig = new RobotstxtConfig(); + RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher); + CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer); + + controller.addSeed("https://www.baeldung.com/"); + + CrawlerStatistics stats = new CrawlerStatistics(); + CrawlController.WebCrawlerFactory factory = () -> new HtmlCrawler(stats); + + controller.start(factory, numCrawlers); + System.out.printf("Crawled %d pages %n", stats.getProcessedPageCount()); + System.out.printf("Total Number of outbound links = %d %n", stats.getTotalLinksCount()); + } + +} diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawler.java b/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawler.java new file mode 100644 index 0000000000..ebb5d96f36 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawler.java @@ -0,0 +1,49 @@ +package com.baeldung.crawler4j; + +import java.io.File; +import java.util.regex.Pattern; + +import edu.uci.ics.crawler4j.crawler.Page; +import edu.uci.ics.crawler4j.crawler.WebCrawler; +import edu.uci.ics.crawler4j.parser.BinaryParseData; +import edu.uci.ics.crawler4j.url.WebURL; + +public class ImageCrawler extends WebCrawler { + private final static Pattern EXCLUSIONS = Pattern.compile(".*(\\.(css|js|xml|gif|png|mp3|mp4|zip|gz|pdf))$"); + + private static final Pattern IMG_PATTERNS = Pattern.compile(".*(\\.(jpg|jpeg))$"); + + private File saveDir; + + public ImageCrawler(File saveDir) { + this.saveDir = saveDir; + } + + @Override + public boolean shouldVisit(Page referringPage, WebURL url) { + String urlString = url.getURL().toLowerCase(); + if (EXCLUSIONS.matcher(urlString).matches()) { + return false; + } + + if (IMG_PATTERNS.matcher(urlString).matches() + || urlString.startsWith("https://www.baeldung.com/")) { + return true; + } + + return false; + } + + @Override + public void visit(Page page) { + String url = page.getWebURL().getURL(); + if (IMG_PATTERNS.matcher(url).matches() + && page.getParseData() instanceof BinaryParseData) { + String extension = url.substring(url.lastIndexOf(".")); + int contentLength = page.getContentData().length; + + System.out.printf("Extension is '%s' with content length %d %n", extension, contentLength); + } + } + +} diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawlerController.java b/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawlerController.java new file mode 100644 index 0000000000..9db32f1bfb --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/ImageCrawlerController.java @@ -0,0 +1,36 @@ +package com.baeldung.crawler4j; + +import java.io.File; + +import edu.uci.ics.crawler4j.crawler.CrawlConfig; +import edu.uci.ics.crawler4j.crawler.CrawlController; +import edu.uci.ics.crawler4j.fetcher.PageFetcher; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtConfig; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtServer; + +public class ImageCrawlerController { + + public static void main(String[] args) throws Exception { + File crawlStorage = new File("src/test/resources/crawler4j"); + CrawlConfig config = new CrawlConfig(); + config.setCrawlStorageFolder(crawlStorage.getAbsolutePath()); + config.setIncludeBinaryContentInCrawling(true); + config.setMaxPagesToFetch(500); + + File saveDir = new File("src/test/resources/crawler4j"); + + int numCrawlers = 12; + + PageFetcher pageFetcher = new PageFetcher(config); + RobotstxtConfig robotstxtConfig = new RobotstxtConfig(); + RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher); + CrawlController controller = new CrawlController(config, pageFetcher, robotstxtServer); + + controller.addSeed("https://www.baeldung.com/"); + + CrawlController.WebCrawlerFactory factory = () -> new ImageCrawler(saveDir); + + controller.start(factory, numCrawlers); + } + +} diff --git a/libraries-2/src/main/java/com/baeldung/crawler4j/MultipleCrawlerController.java b/libraries-2/src/main/java/com/baeldung/crawler4j/MultipleCrawlerController.java new file mode 100644 index 0000000000..7662607f80 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/crawler4j/MultipleCrawlerController.java @@ -0,0 +1,54 @@ +package com.baeldung.crawler4j; + +import java.io.File; + +import edu.uci.ics.crawler4j.crawler.CrawlConfig; +import edu.uci.ics.crawler4j.crawler.CrawlController; +import edu.uci.ics.crawler4j.fetcher.PageFetcher; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtConfig; +import edu.uci.ics.crawler4j.robotstxt.RobotstxtServer; + +public class MultipleCrawlerController { + public static void main(String[] args) throws Exception { + File crawlStorageBase = new File("src/test/resources/crawler4j"); + CrawlConfig htmlConfig = new CrawlConfig(); + CrawlConfig imageConfig = new CrawlConfig(); + + htmlConfig.setCrawlStorageFolder(new File(crawlStorageBase, "html").getAbsolutePath()); + imageConfig.setCrawlStorageFolder(new File(crawlStorageBase, "image").getAbsolutePath()); + imageConfig.setIncludeBinaryContentInCrawling(true); + + htmlConfig.setMaxPagesToFetch(500); + imageConfig.setMaxPagesToFetch(1000); + + PageFetcher pageFetcherHtml = new PageFetcher(htmlConfig); + PageFetcher pageFetcherImage = new PageFetcher(imageConfig); + + RobotstxtConfig robotstxtConfig = new RobotstxtConfig(); + RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcherHtml); + + CrawlController htmlController = new CrawlController(htmlConfig, pageFetcherHtml, robotstxtServer); + CrawlController imageController = new CrawlController(imageConfig, pageFetcherImage, robotstxtServer); + + htmlController.addSeed("https://www.baeldung.com/"); + imageController.addSeed("https://www.baeldung.com/"); + + CrawlerStatistics stats = new CrawlerStatistics(); + CrawlController.WebCrawlerFactory htmlFactory = () -> new HtmlCrawler(stats); + + File saveDir = new File("src/test/resources/crawler4j"); + CrawlController.WebCrawlerFactory imageFactory = () -> new ImageCrawler(saveDir); + + imageController.startNonBlocking(imageFactory, 7); + htmlController.startNonBlocking(htmlFactory, 10); + + + htmlController.waitUntilFinish(); + System.out.printf("Crawled %d pages %n", stats.getProcessedPageCount()); + System.out.printf("Total Number of outbound links = %d %n", stats.getTotalLinksCount()); + + imageController.waitUntilFinish(); + System.out.printf("Image Crawler is finished."); + + } +} diff --git a/libraries-2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java b/libraries-2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java new file mode 100644 index 0000000000..8e54ff892e --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java @@ -0,0 +1,19 @@ +package com.baeldung.jbpm; + +import org.kie.api.runtime.manager.Context; +import org.kie.internal.runtime.manager.context.EmptyContext; + +import com.baeldung.jbpm.engine.WorkflowEngine; +import com.baeldung.jbpm.engine.WorkflowEngineImpl; + +public class WorkflowProcessMain { + + public static void main(String[] args) { + WorkflowEngine workflowEngine = new WorkflowEngineImpl(); + String processId = "com.baeldung.bpmn.helloworld"; + String kbaseId = "kbase"; + String persistenceUnit = "org.jbpm.persistence.jpa"; + Context initialContext = EmptyContext.get(); + workflowEngine.runjBPMEngineForProcess(processId, initialContext, kbaseId, persistenceUnit); + } +} \ No newline at end of file diff --git a/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java new file mode 100644 index 0000000000..b47a4cc8c1 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java @@ -0,0 +1,10 @@ +package com.baeldung.jbpm.engine; + +import org.kie.api.runtime.manager.Context; +import org.kie.api.runtime.process.ProcessInstance; + +public interface WorkflowEngine { + + public ProcessInstance runjBPMEngineForProcess(String processId, Context initialContext, String kbaseId, String persistenceUnit); + +} diff --git a/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java new file mode 100644 index 0000000000..7871241bef --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java @@ -0,0 +1,66 @@ +package com.baeldung.jbpm.engine; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.jbpm.test.JBPMHelper; +import org.kie.api.KieBase; +import org.kie.api.KieServices; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.manager.Context; +import org.kie.api.runtime.manager.RuntimeEngine; +import org.kie.api.runtime.manager.RuntimeEnvironment; +import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder; +import org.kie.api.runtime.manager.RuntimeManager; +import org.kie.api.runtime.manager.RuntimeManagerFactory; +import org.kie.api.runtime.process.ProcessInstance; + +public class WorkflowEngineImpl implements WorkflowEngine { + + @Override + public ProcessInstance runjBPMEngineForProcess(String processId, Context initialContext, String kbaseId, String persistenceUnit) { + RuntimeManager manager = null; + RuntimeEngine engine = null; + ProcessInstance pInstance = null; + try { + KieBase kbase = getKieBase(kbaseId); + manager = createJBPMRuntimeManager(kbase, persistenceUnit); + engine = manager.getRuntimeEngine(initialContext); + pInstance = executeProcessInstance(processId, manager, initialContext, engine); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + if (manager != null && engine != null) + manager.disposeRuntimeEngine(engine); + System.exit(0); + } + return pInstance; + } + + private ProcessInstance executeProcessInstance(String processId, RuntimeManager manager, Context initialContext, RuntimeEngine engine) { + KieSession ksession = engine.getKieSession(); + ProcessInstance pInstance = ksession.startProcess(processId); + return pInstance; + } + + private KieBase getKieBase(String kbaseId) { + KieServices ks = KieServices.Factory.get(); + KieContainer kContainer = ks.getKieClasspathContainer(); + KieBase kbase = kContainer.getKieBase(kbaseId); + return kbase; + } + + private RuntimeManager createJBPMRuntimeManager(KieBase kbase, String persistenceUnit) { + JBPMHelper.startH2Server(); + JBPMHelper.setupDataSource(); + EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit); + RuntimeEnvironmentBuilder runtimeEnvironmentBuilder = RuntimeEnvironmentBuilder.Factory.get() + .newDefaultBuilder(); + RuntimeEnvironment runtimeEnvironment = runtimeEnvironmentBuilder.entityManagerFactory(emf) + .knowledgeBase(kbase) + .get(); + return RuntimeManagerFactory.Factory.get() + .newSingletonRuntimeManager(runtimeEnvironment); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/mesos/HelloWorldMain.java b/libraries-2/src/main/java/com/baeldung/mesos/HelloWorldMain.java new file mode 100644 index 0000000000..e4bf593e7e --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/mesos/HelloWorldMain.java @@ -0,0 +1,42 @@ +package com.baeldung.mesos; + +import com.baeldung.mesos.schedulers.HelloWorldScheduler; +import org.apache.mesos.MesosSchedulerDriver; +import org.apache.mesos.Protos; +import org.apache.mesos.Protos.CommandInfo; +import org.apache.mesos.Protos.ExecutorInfo; +import org.apache.mesos.Protos.FrameworkInfo; + +public class HelloWorldMain { + + public static void main(String[] args) { + + String path = System.getProperty("user.dir") + + "/target/libraries2-1.0.0-SNAPSHOT.jar"; + + CommandInfo.URI uri = CommandInfo.URI.newBuilder().setValue(path).setExtract(false).build(); + + String helloWorldCommand = "java -cp libraries2-1.0.0-SNAPSHOT.jar com.baeldung.mesos.executors.HelloWorldExecutor"; + CommandInfo commandInfoHelloWorld = CommandInfo.newBuilder().setValue(helloWorldCommand).addUris(uri) + .build(); + + ExecutorInfo executorHelloWorld = ExecutorInfo.newBuilder() + .setExecutorId(Protos.ExecutorID.newBuilder().setValue("HelloWorldExecutor")) + .setCommand(commandInfoHelloWorld).setName("Hello World (Java)").setSource("java").build(); + + FrameworkInfo.Builder frameworkBuilder = FrameworkInfo.newBuilder().setFailoverTimeout(120000) + .setUser("") + .setName("Hello World Framework (Java)"); + + frameworkBuilder.setPrincipal("test-framework-java"); + + MesosSchedulerDriver driver = new MesosSchedulerDriver(new HelloWorldScheduler(executorHelloWorld), frameworkBuilder.build(), args[0]); + + int status = driver.run() == Protos.Status.DRIVER_STOPPED ? 0 : 1; + + // Ensure that the driver process terminates. + driver.stop(); + + System.exit(status); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/mesos/executors/HelloWorldExecutor.java b/libraries-2/src/main/java/com/baeldung/mesos/executors/HelloWorldExecutor.java new file mode 100644 index 0000000000..a8620bbce3 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/mesos/executors/HelloWorldExecutor.java @@ -0,0 +1,59 @@ +package com.baeldung.mesos.executors; + +import org.apache.mesos.Executor; +import org.apache.mesos.ExecutorDriver; +import org.apache.mesos.MesosExecutorDriver; +import org.apache.mesos.Protos; +import org.apache.mesos.Protos.TaskInfo; + +public class HelloWorldExecutor implements Executor { + @Override + public void registered(ExecutorDriver driver, Protos.ExecutorInfo executorInfo, Protos.FrameworkInfo frameworkInfo, Protos.SlaveInfo slaveInfo) { + } + + @Override + public void reregistered(ExecutorDriver driver, Protos.SlaveInfo slaveInfo) { + } + + @Override + public void disconnected(ExecutorDriver driver) { + } + + @Override + public void launchTask(ExecutorDriver driver, TaskInfo task) { + + Protos.TaskStatus status = Protos.TaskStatus.newBuilder().setTaskId(task.getTaskId()) + .setState(Protos.TaskState.TASK_RUNNING).build(); + driver.sendStatusUpdate(status); + + String myStatus = "Hello Framework"; + driver.sendFrameworkMessage(myStatus.getBytes()); + + System.out.println("Hello World!!!"); + + status = Protos.TaskStatus.newBuilder().setTaskId(task.getTaskId()) + .setState(Protos.TaskState.TASK_FINISHED).build(); + driver.sendStatusUpdate(status); + } + + @Override + public void killTask(ExecutorDriver driver, Protos.TaskID taskId) { + } + + @Override + public void frameworkMessage(ExecutorDriver driver, byte[] data) { + } + + @Override + public void shutdown(ExecutorDriver driver) { + } + + @Override + public void error(ExecutorDriver driver, String message) { + } + + public static void main(String[] args) { + MesosExecutorDriver driver = new MesosExecutorDriver(new HelloWorldExecutor()); + System.exit(driver.run() == Protos.Status.DRIVER_STOPPED ? 0 : 1); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/mesos/schedulers/HelloWorldScheduler.java b/libraries-2/src/main/java/com/baeldung/mesos/schedulers/HelloWorldScheduler.java new file mode 100644 index 0000000000..68808b4dd0 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/mesos/schedulers/HelloWorldScheduler.java @@ -0,0 +1,100 @@ +package com.baeldung.mesos.schedulers; + +import com.google.protobuf.ByteString; +import org.apache.mesos.Protos; +import org.apache.mesos.Protos.ExecutorInfo; +import org.apache.mesos.Protos.Offer; +import org.apache.mesos.Protos.OfferID; +import org.apache.mesos.Protos.TaskInfo; +import org.apache.mesos.Scheduler; +import org.apache.mesos.SchedulerDriver; + +import java.util.ArrayList; +import java.util.List; + +public class HelloWorldScheduler implements Scheduler { + + private int launchedTasks = 0; + private final ExecutorInfo helloWorldExecutor; + + public HelloWorldScheduler(ExecutorInfo helloWorldExecutor) { + this.helloWorldExecutor = helloWorldExecutor; + } + + @Override + public void registered(SchedulerDriver schedulerDriver, Protos.FrameworkID frameworkID, Protos.MasterInfo masterInfo) { + + } + + @Override + public void reregistered(SchedulerDriver schedulerDriver, Protos.MasterInfo masterInfo) { + + } + + @Override + public void resourceOffers(SchedulerDriver schedulerDriver, List list) { + + for (Offer offer : list) { + List tasks = new ArrayList(); + Protos.TaskID taskId = Protos.TaskID.newBuilder().setValue(Integer.toString(launchedTasks++)).build(); + + System.out.println("Launching printHelloWorld " + taskId.getValue() + " Hello World Java"); + TaskInfo printHelloWorld = TaskInfo + .newBuilder() + .setName("printHelloWorld " + taskId.getValue()) + .setTaskId(taskId) + .setSlaveId(offer.getSlaveId()) + .addResources( + Protos.Resource.newBuilder().setName("cpus").setType(Protos.Value.Type.SCALAR) + .setScalar(Protos.Value.Scalar.newBuilder().setValue(1))) + .addResources( + Protos.Resource.newBuilder().setName("mem").setType(Protos.Value.Type.SCALAR) + .setScalar(Protos.Value.Scalar.newBuilder().setValue(128))) + .setExecutor(ExecutorInfo.newBuilder(helloWorldExecutor)).build(); + + List offerIDS = new ArrayList<>(); + offerIDS.add(offer.getId()); + + tasks.add(printHelloWorld); + + schedulerDriver.declineOffer(offer.getId()); + schedulerDriver.launchTasks(offerIDS, tasks); + } + + } + + @Override + public void offerRescinded(SchedulerDriver schedulerDriver, OfferID offerID) { + + } + + @Override + public void statusUpdate(SchedulerDriver schedulerDriver, Protos.TaskStatus taskStatus) { + + } + + @Override + public void frameworkMessage(SchedulerDriver schedulerDriver, Protos.ExecutorID executorID, Protos.SlaveID slaveID, byte[] bytes) { + + } + + @Override + public void disconnected(SchedulerDriver schedulerDriver) { + + } + + @Override + public void slaveLost(SchedulerDriver schedulerDriver, Protos.SlaveID slaveID) { + + } + + @Override + public void executorLost(SchedulerDriver schedulerDriver, Protos.ExecutorID executorID, Protos.SlaveID slaveID, int i) { + + } + + @Override + public void error(SchedulerDriver schedulerDriver, String s) { + + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/Application.java b/libraries-2/src/main/java/com/baeldung/picocli/git/Application.java new file mode 100644 index 0000000000..04af524e45 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/Application.java @@ -0,0 +1,41 @@ +package com.baeldung.picocli.git; + +import com.baeldung.picocli.git.commands.programmative.GitCommand; +import com.baeldung.picocli.git.commands.subcommands.GitAddCommand; +import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand; +import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import picocli.CommandLine; + +@SpringBootApplication +public class Application implements CommandLineRunner { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + private GitCommand gitCommand; + private GitAddCommand addCommand; + private GitCommitCommand commitCommand; + private GitConfigCommand configCommand; + + @Autowired + public Application(GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commitCommand, GitConfigCommand configCommand) { + this.gitCommand = gitCommand; + this.addCommand = addCommand; + this.commitCommand = commitCommand; + this.configCommand = configCommand; + } + + @Override + public void run(String... args) { + CommandLine commandLine = new CommandLine(gitCommand); + commandLine.addSubcommand("add", addCommand); + commandLine.addSubcommand("commit", commitCommand); + commandLine.addSubcommand("config", configCommand); + + commandLine.parseWithHandler(new CommandLine.RunLast(), args); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java new file mode 100644 index 0000000000..f3c690a3e6 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java @@ -0,0 +1,32 @@ +package com.baeldung.picocli.git.commands.declarative; + +import com.baeldung.picocli.git.model.ConfigElement; +import com.baeldung.picocli.git.commands.subcommands.GitAddCommand; +import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand; +import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand; +import picocli.CommandLine; + +import static picocli.CommandLine.*; +import static picocli.CommandLine.Command; + +@Command( + name = "git", + subcommands = { + GitAddCommand.class, + GitCommitCommand.class, + GitConfigCommand.class + } +) +public class GitCommand implements Runnable { + public static void main(String[] args) { + CommandLine commandLine = new CommandLine(new GitCommand()); + commandLine.registerConverter(ConfigElement.class, ConfigElement::from); + + commandLine.parseWithHandler(new RunLast(), args); + } + + @Override + public void run() { + System.out.println("The popular git command"); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java new file mode 100644 index 0000000000..2c3e440b8b --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java @@ -0,0 +1,27 @@ +package com.baeldung.picocli.git.commands.methods; + +import picocli.CommandLine; + +import static picocli.CommandLine.Command; + +@Command(name = "git") +public class GitCommand implements Runnable { + public static void main(String[] args) { + CommandLine.run(new GitCommand(), args); + } + + @Override + public void run() { + System.out.println("The popular git command"); + } + + @Command(name = "add") + public void addCommand() { + System.out.println("Adding some files to the staging area"); + } + + @Command(name = "commit") + public void commitCommand() { + System.out.println("Committing files in the staging area, how wonderful?"); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java new file mode 100644 index 0000000000..81ecfd78be --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java @@ -0,0 +1,26 @@ +package com.baeldung.picocli.git.commands.programmative; + +import com.baeldung.picocli.git.commands.subcommands.GitAddCommand; +import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand; +import org.springframework.stereotype.Component; +import picocli.CommandLine; + +import static picocli.CommandLine.Command; +import static picocli.CommandLine.RunLast; + +@Command(name = "git") +@Component +public class GitCommand implements Runnable { + public static void main(String[] args) { + CommandLine commandLine = new CommandLine(new GitCommand()); + commandLine.addSubcommand("add", new GitAddCommand()); + commandLine.addSubcommand("commit", new GitCommitCommand()); + + commandLine.parseWithHandler(new RunLast(), args); + } + + @Override + public void run() { + System.out.println("The popular git command"); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java new file mode 100644 index 0000000000..803cd8dc7d --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java @@ -0,0 +1,31 @@ +package com.baeldung.picocli.git.commands.subcommands; + +import org.springframework.stereotype.Component; + +import java.nio.file.Path; +import java.util.List; + +import static picocli.CommandLine.*; + +@Command( + name = "add" +) +@Component +public class GitAddCommand implements Runnable { + @Option(names = "-A") + private boolean allFiles; + + @Parameters(index = "0..*") + private List files; + + @Override + public void run() { + if (allFiles) { + System.out.println("Adding all files to the staging area"); + } + + if (files != null) { + files.forEach(path -> System.out.println("Adding " + path + " to the staging area")); + } + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java new file mode 100644 index 0000000000..df4928983c --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java @@ -0,0 +1,26 @@ +package com.baeldung.picocli.git.commands.subcommands; + +import org.springframework.stereotype.Component; + +import static picocli.CommandLine.Command; +import static picocli.CommandLine.Option; + +@Command( + name = "commit" +) +@Component +public class GitCommitCommand implements Runnable { + @Option(names = {"-m", "--message"}, required = true) + private String[] messages; + + @Override + public void run() { + System.out.println("Committing files in the staging area, how wonderful?"); + if (messages != null) { + System.out.println("The commit message is"); + for (String message : messages) { + System.out.println(message); + } + } + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java new file mode 100644 index 0000000000..80e14c0121 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java @@ -0,0 +1,24 @@ +package com.baeldung.picocli.git.commands.subcommands; + +import com.baeldung.picocli.git.model.ConfigElement; +import org.springframework.stereotype.Component; + +import static picocli.CommandLine.Command; +import static picocli.CommandLine.Parameters; + +@Command( + name = "config" +) +@Component +public class GitConfigCommand implements Runnable { + @Parameters(index = "0") + private ConfigElement element; + + @Parameters(index = "1") + private String value; + + @Override + public void run() { + System.out.println("Setting " + element.value() + " to " + value); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java b/libraries-2/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java new file mode 100644 index 0000000000..edc6573d88 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java @@ -0,0 +1,25 @@ +package com.baeldung.picocli.git.model; + +import java.util.Arrays; + +public enum ConfigElement { + USERNAME("user.name"), + EMAIL("user.email"); + + private final String value; + + ConfigElement(String value) { + this.value = value; + } + + public String value() { + return value; + } + + public static ConfigElement from(String value) { + return Arrays.stream(values()) + .filter(element -> element.value.equals(value)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("The argument " + value + " doesn't match any ConfigElement")); + } +} diff --git a/libraries-2/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java b/libraries-2/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java new file mode 100644 index 0000000000..97a861e2f0 --- /dev/null +++ b/libraries-2/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java @@ -0,0 +1,20 @@ +package com.baeldung.picocli.helloworld; + +import picocli.CommandLine; + +import static picocli.CommandLine.Command; + +@Command( + name = "hello", + description = "Says hello" +) +public class HelloWorldCommand implements Runnable { + public static void main(String[] args) { + CommandLine.run(new HelloWorldCommand(), args); + } + + @Override + public void run() { + System.out.println("Hello World!"); + } +} diff --git a/libraries-2/src/main/resources/META-INF/kmodule.xml b/libraries-2/src/main/resources/META-INF/kmodule.xml new file mode 100644 index 0000000000..1b9ce1ce71 --- /dev/null +++ b/libraries-2/src/main/resources/META-INF/kmodule.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/libraries-2/src/main/resources/com/baeldung/process/helloworld.bpmn b/libraries-2/src/main/resources/com/baeldung/process/helloworld.bpmn new file mode 100644 index 0000000000..30813b2057 --- /dev/null +++ b/libraries-2/src/main/resources/com/baeldung/process/helloworld.bpmn @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/chroniclemap/ChronicleMapUnitTest.java b/libraries-2/src/test/java/com/baeldung/chroniclemap/ChronicleMapUnitTest.java new file mode 100644 index 0000000000..7f36a9abdb --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/chroniclemap/ChronicleMapUnitTest.java @@ -0,0 +1,132 @@ +package com.baeldung.chroniclemap; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import net.openhft.chronicle.core.values.LongValue; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.map.ExternalMapQueryContext; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.values.Values; + +public class ChronicleMapUnitTest { + + static ChronicleMap persistedCountryMap = null; + + static ChronicleMap inMemoryCountryMap = null; + + static ChronicleMap> multiMap = null; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @BeforeClass + public static void init() { + try { + inMemoryCountryMap = ChronicleMap.of(LongValue.class, CharSequence.class) + .name("country-map") + .entries(50) + .averageValue("America") + .create(); + + persistedCountryMap = ChronicleMap.of(LongValue.class, CharSequence.class) + .name("country-map") + .entries(50) + .averageValue("America") + .createPersistedTo(new File(System.getProperty("user.home") + "/country-details.dat")); + + Set averageValue = IntStream.of(1, 2) + .boxed() + .collect(Collectors.toSet()); + multiMap = ChronicleMap.of(Integer.class, (Class>) (Class) Set.class) + .name("multi-map") + .entries(50) + .averageValue(averageValue) + .create(); + + LongValue qatarKey = Values.newHeapInstance(LongValue.class); + qatarKey.setValue(1); + inMemoryCountryMap.put(qatarKey, "Qatar"); + + LongValue key = Values.newHeapInstance(LongValue.class); + key.setValue(1); + persistedCountryMap.put(key, "Romania"); + key.setValue(2); + persistedCountryMap.put(key, "India"); + + Set set1 = new HashSet<>(); + set1.add(1); + set1.add(2); + multiMap.put(1, set1); + + Set set2 = new HashSet<>(); + set2.add(3); + multiMap.put(2, set2); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void givenGetQuery_whenCalled_shouldReturnResult() { + LongValue key = Values.newHeapInstance(LongValue.class); + key.setValue(1); + CharSequence country = inMemoryCountryMap.get(key); + assertThat(country.toString(), is(equalTo("Qatar"))); + } + + @Test + public void givenGetUsingQuery_whenCalled_shouldReturnResult() { + LongValue key = Values.newHeapInstance(LongValue.class); + StringBuilder country = new StringBuilder(); + key.setValue(1); + persistedCountryMap.getUsing(key, country); + assertThat(country.toString(), is(equalTo("Romania"))); + key.setValue(2); + persistedCountryMap.getUsing(key, country); + assertThat(country.toString(), is(equalTo("India"))); + } + + @Test + public void givenMultipleKeyQuery_whenProcessed_shouldChangeTheValue() { + try (ExternalMapQueryContext, ?> fistContext = multiMap.queryContext(1)) { + try (ExternalMapQueryContext, ?> secondContext = multiMap.queryContext(2)) { + fistContext.updateLock() + .lock(); + secondContext.updateLock() + .lock(); + MapEntry> firstEntry = fistContext.entry(); + Set firstSet = firstEntry.value() + .get(); + firstSet.remove(2); + MapEntry> secondEntry = secondContext.entry(); + Set secondSet = secondEntry.value() + .get(); + secondSet.add(4); + firstEntry.doReplaceValue(fistContext.wrapValueAsData(firstSet)); + secondEntry.doReplaceValue(secondContext.wrapValueAsData(secondSet)); + } + } finally { + assertThat(multiMap.get(1) + .size(), is(equalTo(1))); + assertThat(multiMap.get(2) + .size(), is(equalTo(2))); + } + } + + @AfterClass + public static void finish() { + persistedCountryMap.close(); + inMemoryCountryMap.close(); + multiMap.close(); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/ClassGraphUnitTest.java b/libraries-2/src/test/java/com/baeldung/classgraph/ClassGraphUnitTest.java new file mode 100644 index 0000000000..3dc99e6a32 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/ClassGraphUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.classgraph; + +import io.github.classgraph.*; +import org.junit.Test; + +import java.io.IOException; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ClassGraphUnitTest { + + @Test + public void whenClassAnnotationFilterIsDefined_thenTargetClassesCanBeFound() { + doTest(result -> { + ClassInfoList classInfos = result.getClassesWithAnnotation(TestAnnotation.class.getName()); + assertThat(classInfos).extracting(ClassInfo::getName).contains(ClassWithAnnotation.class.getName()); + }); + } + + @Test + public void whenMethodAnnotationFilterIsDefined_thenTargetClassesCanBeFound() { + doTest(result -> { + ClassInfoList classInfos = result.getClassesWithMethodAnnotation(TestAnnotation.class.getName()); + assertThat(classInfos).extracting(ClassInfo::getName).contains(MethodWithAnnotation.class.getName()); + }); + } + + @Test + public void whenMethodAnnotationValueFilterIsDefined_thenTargetClassesCanBeFound() { + doTest(result -> { + ClassInfoList classInfos = result.getClassesWithMethodAnnotation(TestAnnotation.class.getName()); + ClassInfoList filteredClassInfos = classInfos.filter(classInfo -> { + return classInfo.getMethodInfo().stream().anyMatch(methodInfo -> { + AnnotationInfo annotationInfo = methodInfo.getAnnotationInfo(TestAnnotation.class.getName()); + if (annotationInfo == null) { + return false; + } + + return "web".equals(annotationInfo.getParameterValues().getValue("value")); + }); + }); + assertThat(filteredClassInfos) + .extracting(ClassInfo::getName) + .contains(MethodWithAnnotationParameterWeb.class.getName()); + }); + } + + @Test + public void whenFieldAnnotationFilterIsDefined_thenTargetClassesCanBeFound() { + doTest(result -> { + ClassInfoList classInfos = result.getClassesWithFieldAnnotation(TestAnnotation.class.getName()); + assertThat(classInfos).extracting(ClassInfo::getName).contains(FieldWithAnnotation.class.getName()); + }); + } + + @Test + public void whenResourceIsUsed_thenItCanBeFoundAndLoaded() throws IOException { + try (ScanResult result = new ClassGraph().whitelistPaths("classgraph").scan()) { + ResourceList resources = result.getResourcesWithExtension("config"); + assertThat(resources).extracting(Resource::getPath).containsOnly("classgraph/my.config"); + assertThat(resources.get(0).getContentAsString()).isEqualTo("my data"); + } + } + + private void doTest(Consumer checker) { + try (ScanResult result = new ClassGraph().enableAllInfo() + .whitelistPackages(getClass().getPackage().getName()) + .scan()) + { + checker.accept(result); + } + } +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/ClassWithAnnotation.java b/libraries-2/src/test/java/com/baeldung/classgraph/ClassWithAnnotation.java new file mode 100644 index 0000000000..fe476769a6 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/ClassWithAnnotation.java @@ -0,0 +1,5 @@ +package com.baeldung.classgraph; + +@TestAnnotation +public class ClassWithAnnotation { +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/FieldWithAnnotation.java b/libraries-2/src/test/java/com/baeldung/classgraph/FieldWithAnnotation.java new file mode 100644 index 0000000000..f72a7621f9 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/FieldWithAnnotation.java @@ -0,0 +1,7 @@ +package com.baeldung.classgraph; + +public class FieldWithAnnotation { + + @TestAnnotation + private String s; +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotation.java b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotation.java new file mode 100644 index 0000000000..29a59c09ea --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotation.java @@ -0,0 +1,8 @@ +package com.baeldung.classgraph; + +public class MethodWithAnnotation { + + @TestAnnotation + public void service() { + } +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterDao.java b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterDao.java new file mode 100644 index 0000000000..f01c2743eb --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterDao.java @@ -0,0 +1,8 @@ +package com.baeldung.classgraph; + +public class MethodWithAnnotationParameterDao { + + @TestAnnotation("dao") + public void service() { + } +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterWeb.java b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterWeb.java new file mode 100644 index 0000000000..bf01f7d23c --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/MethodWithAnnotationParameterWeb.java @@ -0,0 +1,8 @@ +package com.baeldung.classgraph; + +public class MethodWithAnnotationParameterWeb { + + @TestAnnotation("web") + public void service() { + } +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/classgraph/TestAnnotation.java b/libraries-2/src/test/java/com/baeldung/classgraph/TestAnnotation.java new file mode 100644 index 0000000000..e3f5df92ed --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/classgraph/TestAnnotation.java @@ -0,0 +1,14 @@ +package com.baeldung.classgraph; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +@Target({TYPE, METHOD, FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface TestAnnotation { + + String value() default ""; +} \ No newline at end of file diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/BasicUsageUnitTest.java b/libraries-2/src/test/java/com/baeldung/handlebars/BasicUsageUnitTest.java new file mode 100644 index 0000000000..3eb325dbb6 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/BasicUsageUnitTest.java @@ -0,0 +1,109 @@ +package com.baeldung.handlebars; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.io.ClassPathTemplateLoader; +import com.github.jknack.handlebars.io.TemplateLoader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +/** + * Showcases the tag usage and different template loading mechanisms. + * + * @author isaolmez + */ +public class BasicUsageUnitTest { + + @Test + public void whenThereIsNoTemplateFile_ThenCompilesInline() throws IOException { + Handlebars handlebars = new Handlebars(); + Template template = handlebars.compileInline("Hi {{this}}!"); + + String templateString = template.apply("Baeldung"); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + @Test + public void whenParameterMapIsSupplied_thenDisplays() throws IOException { + Handlebars handlebars = new Handlebars(); + Template template = handlebars.compileInline("Hi {{name}}!"); + Map parameterMap = new HashMap<>(); + parameterMap.put("name", "Baeldung"); + + String templateString = template.apply(parameterMap); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + @Test + public void whenParameterObjectIsSupplied_ThenDisplays() throws IOException { + Handlebars handlebars = new Handlebars(); + Template template = handlebars.compileInline("Hi {{name}}!"); + Person person = new Person(); + person.setName("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + @Test + public void whenMultipleParametersAreSupplied_ThenDisplays() throws IOException { + Handlebars handlebars = new Handlebars(); + Template template = handlebars.compileInline("Hi {{name}}! This is {{topic}}."); + Map parameterMap = new HashMap<>(); + parameterMap.put("name", "Baeldung"); + parameterMap.put("topic", "Handlebars"); + + String templateString = template.apply(parameterMap); + + assertThat(templateString).isEqualTo("Hi Baeldung! This is Handlebars."); + } + + @Test + public void whenNoLoaderIsGiven_ThenSearchesClasspath() throws IOException { + Handlebars handlebars = new Handlebars(); + Template template = handlebars.compile("greeting"); + Person person = getPerson("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + @Test + public void whenClasspathTemplateLoaderIsGiven_ThenSearchesClasspathWithPrefixSuffix() throws IOException { + TemplateLoader loader = new ClassPathTemplateLoader("/handlebars", ".html"); + Handlebars handlebars = new Handlebars(loader); + Template template = handlebars.compile("greeting"); + Person person = getPerson("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + @Test + public void whenMultipleLoadersAreGiven_ThenSearchesSequentially() throws IOException { + TemplateLoader firstLoader = new ClassPathTemplateLoader("/handlebars", ".html"); + TemplateLoader secondLoader = new ClassPathTemplateLoader("/templates", ".html"); + Handlebars handlebars = new Handlebars().with(firstLoader, secondLoader); + Template template = handlebars.compile("greeting"); + Person person = getPerson("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Hi Baeldung!"); + } + + private Person getPerson(String name) { + Person person = new Person(); + person.setName(name); + return person; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/BuiltinHelperUnitTest.java b/libraries-2/src/test/java/com/baeldung/handlebars/BuiltinHelperUnitTest.java new file mode 100644 index 0000000000..6749f7fe0a --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/BuiltinHelperUnitTest.java @@ -0,0 +1,106 @@ +package com.baeldung.handlebars; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.io.ClassPathTemplateLoader; +import com.github.jknack.handlebars.io.TemplateLoader; +import java.io.IOException; +import org.junit.Test; + +/** + * Showcases the built-in template helpers. + * + * @author isaolmez + */ +public class BuiltinHelperUnitTest { + + private TemplateLoader templateLoader = new ClassPathTemplateLoader("/handlebars", ".html"); + + @Test + public void whenUsedWith_ThenContextChanges() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("with"); + Person person = getPerson("Baeldung"); + person.getAddress().setStreet("World"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\n

I live in World

\n"); + } + + @Test + public void whenUsedWithMustacheStyle_ThenContextChanges() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("with_mustache"); + Person person = getPerson("Baeldung"); + person.getAddress().setStreet("World"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\n

I live in World

\n"); + } + + @Test + public void whenUsedEach_ThenIterates() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("each"); + Person person = getPerson("Baeldung"); + Person friend1 = getPerson("Java"); + Person friend2 = getPerson("Spring"); + person.getFriends().add(friend1); + person.getFriends().add(friend2); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\nJava is my friend.\n" + + "\nSpring is my friend.\n"); + } + + @Test + public void whenUsedEachMustacheStyle_ThenIterates() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("each_mustache"); + Person person = getPerson("Baeldung"); + Person friend1 = getPerson("Java"); + Person friend2 = getPerson("Spring"); + person.getFriends().add(friend1); + person.getFriends().add(friend2); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\nJava is my friend.\n" + + "\nSpring is my friend.\n"); + } + + @Test + public void whenUsedIf_ThenPutsCondition() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("if"); + Person person = getPerson("Baeldung"); + person.setBusy(true); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\n

Baeldung is busy.

\n"); + } + + @Test + public void whenUsedIfMustacheStyle_ThenPutsCondition() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("if_mustache"); + Person person = getPerson("Baeldung"); + person.setBusy(true); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\n

Baeldung is busy.

\n"); + } + + private Person getPerson(String name) { + Person person = new Person(); + person.setName(name); + return person; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/CustomHelperUnitTest.java b/libraries-2/src/test/java/com/baeldung/handlebars/CustomHelperUnitTest.java new file mode 100644 index 0000000000..a3c6667654 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/CustomHelperUnitTest.java @@ -0,0 +1,59 @@ +package com.baeldung.handlebars; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.io.ClassPathTemplateLoader; +import com.github.jknack.handlebars.io.TemplateLoader; +import java.io.IOException; +import org.junit.Test; + +/** + * Showcases implementing a custom template helper. + * + * @author isaolmez + */ +public class CustomHelperUnitTest { + + private TemplateLoader templateLoader = new ClassPathTemplateLoader("/handlebars", ".html"); + + @Test + public void whenHelperIsCreated_ThenCanRegister() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + handlebars.registerHelper("isBusy", new Helper() { + @Override + public Object apply(Person context, Options options) throws IOException { + String busyString = context.isBusy() ? "busy" : "available"; + return context.getName() + " - " + busyString; + } + }); + Template template = handlebars.compile("person"); + Person person = getPerson("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Baeldung - busy"); + } + + @Test + public void whenHelperSourceIsCreated_ThenCanRegister() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + handlebars.registerHelpers(new HelperSource()); + Template template = handlebars.compile("person"); + Person person = getPerson("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("Baeldung - busy"); + } + + private Person getPerson(String name) { + Person person = new Person(); + person.setName(name); + person.setBusy(true); + return person; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/HelperSource.java b/libraries-2/src/test/java/com/baeldung/handlebars/HelperSource.java new file mode 100644 index 0000000000..b98786c029 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/HelperSource.java @@ -0,0 +1,9 @@ +package com.baeldung.handlebars; + +public class HelperSource { + + public String isBusy(Person context) { + String busyString = context.isBusy() ? "busy" : "available"; + return context.getName() + " - " + busyString; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/Person.java b/libraries-2/src/test/java/com/baeldung/handlebars/Person.java new file mode 100644 index 0000000000..9ddc0fdffb --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/Person.java @@ -0,0 +1,58 @@ +package com.baeldung.handlebars; + +import java.util.ArrayList; +import java.util.List; + +public class Person { + + private String name; + private boolean busy; + private Address address = new Address(); + private List friends = new ArrayList<>(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isBusy() { + return busy; + } + + public void setBusy(boolean busy) { + this.busy = busy; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public List getFriends() { + return friends; + } + + public void setFriends(List friends) { + this.friends = friends; + } + + public static class Address { + + private String street; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/handlebars/ReusingTemplatesUnitTest.java b/libraries-2/src/test/java/com/baeldung/handlebars/ReusingTemplatesUnitTest.java new file mode 100644 index 0000000000..36f78f486e --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/handlebars/ReusingTemplatesUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.handlebars; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.io.ClassPathTemplateLoader; +import com.github.jknack.handlebars.io.TemplateLoader; +import java.io.IOException; +import org.junit.Test; + +/** + * Showcases reusing the existing templates. + * + * @author isaolmez + */ +public class ReusingTemplatesUnitTest { + + private TemplateLoader templateLoader = new ClassPathTemplateLoader("/handlebars", ".html"); + + @Test + public void whenOtherTemplateIsReferenced_ThenCanReuse() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("page"); + Person person = new Person(); + person.setName("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("

Hi Baeldung!

\n

This is the page Baeldung

"); + } + + @Test + public void whenBlockIsDefined_ThenCanOverrideWithPartial() throws IOException { + Handlebars handlebars = new Handlebars(templateLoader); + Template template = handlebars.compile("simplemessage"); + Person person = new Person(); + person.setName("Baeldung"); + + String templateString = template.apply(person); + + assertThat(templateString).isEqualTo("\n\n" + + "\n" + + "\n This is the intro\n\n" + + "\n Hi there!\n\n" + + "\n" + + ""); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java b/libraries-2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java new file mode 100644 index 0000000000..ded46d7639 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java @@ -0,0 +1,52 @@ +package com.baeldung.jbpm; + +import org.jbpm.test.JbpmJUnitBaseTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.manager.RuntimeEngine; +import org.kie.api.runtime.manager.RuntimeManager; +import org.kie.api.runtime.process.ProcessInstance; +import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext; + +public class WorkflowEngineIntegrationTest extends JbpmJUnitBaseTestCase { + + private String[] triggeredNodesArray = { "Start", "HelloWorld", "End" }; + private RuntimeManager manager = null; + private RuntimeEngine runtimeEngine = null; + private KieSession ksession = null; + private ProcessInstance processInstance = null; + + @Before + public void setup() { + manager = createRuntimeManager(Strategy.SINGLETON, "manager", "com/baeldung/process/helloworld.bpmn"); + runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get()); + ksession = runtimeEngine.getKieSession(); + processInstance = ksession.startProcess("com.baeldung.bpmn.helloworld"); + } + + @After + public void cleanup() { + manager.disposeRuntimeEngine(runtimeEngine); + } + + @Test + public void givenProcessInstance_whenExecutionCompleted_thenVerifyNodesExecutionOrder() { + assertNodeTriggered(processInstance.getId(), triggeredNodesArray); + } + + @Test + public void givenProcessInstance_whenExecutionCompleted_thenVerifyKnowledgeSessionId() { + int ksessionID = ksession.getId(); + runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get(processInstance.getId())); + ksession = runtimeEngine.getKieSession(); + assertEquals(ksessionID, ksession.getId()); + } + + @Test + public void givenProcessInstance_whenExecutionCompleted_thenVerifyProcessInstanceStatus() { + assertProcessInstanceCompleted(processInstance.getId(), ksession); + assertTrue("ProcessInstance completed with status 2", processInstance.getState() == 2); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/CollectionsUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/CollectionsUnitTest.java new file mode 100644 index 0000000000..6f5141b054 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/CollectionsUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.mapdb; + +import org.junit.Test; +import org.mapdb.DB; +import org.mapdb.DBMaker; +import org.mapdb.Serializer; + +import java.util.NavigableSet; + +import static junit.framework.Assert.assertEquals; + +public class CollectionsUnitTest { + + @Test + public void givenSetCreatedInDB_whenMultipleElementsAdded_checkOnlyOneExists() { + + DB db = DBMaker.memoryDB().make(); + + NavigableSet set = db. + treeSet("mySet") + .serializer(Serializer.STRING) + .createOrOpen(); + + String myString = "Baeldung!"; + + set.add(myString); + set.add(myString); + + assertEquals(1, set.size()); + + db.close(); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/HTreeMapUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/HTreeMapUnitTest.java new file mode 100644 index 0000000000..3b7cac04fb --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/HTreeMapUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.mapdb; + +import org.jetbrains.annotations.NotNull; +import org.junit.Test; +import org.mapdb.*; + +import java.io.IOException; + +import static junit.framework.Assert.assertEquals; + +public class HTreeMapUnitTest { + + @Test + public void givenValidDB_whenHTreeMapAddedToAndRetrieved_CheckedRetrievalCorrect() { + + DB db = DBMaker.memoryDB().make(); + + HTreeMap hTreeMap = db + .hashMap("myTreMap") + .keySerializer(Serializer.STRING) + .valueSerializer(Serializer.STRING) + .create(); + + hTreeMap.put("key1", "value1"); + hTreeMap.put("key2", "value2"); + + assertEquals(2, hTreeMap.size()); + + //add another value with the same key + + hTreeMap.put("key1", "value3"); + + assertEquals(2, hTreeMap.size()); + assertEquals("value3", hTreeMap.get("key1")); + + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/HelloBaeldungUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/HelloBaeldungUnitTest.java new file mode 100644 index 0000000000..952efd0639 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/HelloBaeldungUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.mapdb; + +import org.junit.Test; +import org.mapdb.DB; +import org.mapdb.DBMaker; +import org.mapdb.HTreeMap; + +import java.util.concurrent.ConcurrentMap; + +import static junit.framework.Assert.assertEquals; + +public class HelloBaeldungUnitTest { + + @Test + public void givenInMemoryDBInstantiateCorrectly_whenDataSavedAndRetrieved_checkRetrievalCorrect() { + + DB db = DBMaker.memoryDB().make(); + + String welcomeMessageKey = "Welcome Message"; + String welcomeMessageString = "Hello Baeldung!"; + + HTreeMap myMap = db.hashMap("myMap").createOrOpen(); + myMap.put(welcomeMessageKey, welcomeMessageString); + + String welcomeMessageFromDB = (String) myMap.get(welcomeMessageKey); + + db.close(); + + assertEquals(welcomeMessageString, welcomeMessageFromDB); + } + + @Test + public void givenInFileDBInstantiateCorrectly_whenDataSavedAndRetrieved_checkRetrievalCorrect() { + + DB db = DBMaker.fileDB("file.db").make(); + + String welcomeMessageKey = "Welcome Message"; + String welcomeMessageString = "Hello Baeldung!"; + + HTreeMap myMap = db.hashMap("myMap").createOrOpen(); + myMap.put(welcomeMessageKey, welcomeMessageString); + + String welcomeMessageFromDB = (String) myMap.get(welcomeMessageKey); + + db.close(); + + assertEquals(welcomeMessageString, welcomeMessageFromDB); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/InMemoryModesUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/InMemoryModesUnitTest.java new file mode 100644 index 0000000000..9c53f9c792 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/InMemoryModesUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.mapdb; + +import org.junit.Test; +import org.mapdb.DB; +import org.mapdb.DBMaker; +import org.mapdb.HTreeMap; +import org.mapdb.Serializer; + +import static junit.framework.Assert.assertEquals; + +public class InMemoryModesUnitTest { + + @Test + public void givenDBCreatedOnHeap_whenUsed_checkUsageCorrect() { + + DB heapDB = DBMaker.heapDB().make(); + + HTreeMap map = heapDB + .hashMap("myMap") + .keySerializer(Serializer.INTEGER) + .valueSerializer(Serializer.STRING) + .createOrOpen(); + + map.put(1, "ONE"); + + assertEquals("ONE", map.get(1)); + + } + + @Test + public void givenDBCreatedBaseOnByteArray_whenUsed_checkUsageCorrect() { + + DB heapDB = DBMaker.memoryDB().make(); + + HTreeMap map = heapDB + .hashMap("myMap") + .keySerializer(Serializer.INTEGER) + .valueSerializer(Serializer.STRING) + .createOrOpen(); + + map.put(1, "ONE"); + + assertEquals("ONE", map.get(1)); + } + + @Test + public void givenDBCreatedBaseOnDirectByteBuffer_whenUsed_checkUsageCorrect() { + + DB heapDB = DBMaker.memoryDirectDB().make(); + + HTreeMap map = heapDB + .hashMap("myMap") + .keySerializer(Serializer.INTEGER) + .valueSerializer(Serializer.STRING) + .createOrOpen(); + + map.put(1, "ONE"); + + assertEquals("ONE", map.get(1)); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/SortedTableMapUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/SortedTableMapUnitTest.java new file mode 100644 index 0000000000..83ba917393 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/SortedTableMapUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.mapdb; + +import org.junit.Test; +import org.mapdb.Serializer; +import org.mapdb.SortedTableMap; +import org.mapdb.volume.MappedFileVol; +import org.mapdb.volume.Volume; + +import static junit.framework.Assert.assertEquals; + +public class SortedTableMapUnitTest { + + private static final String VOLUME_LOCATION = "sortedTableMapVol.db"; + + @Test + public void givenValidSortedTableMapSetup_whenQueried_checkValuesCorrect() { + + //create memory mapped volume, readonly false + Volume vol = MappedFileVol.FACTORY.makeVolume(VOLUME_LOCATION, false); + + //create sink to feed the map with data + SortedTableMap.Sink sink = + SortedTableMap.create( + vol, + Serializer.INTEGER, + Serializer.STRING + ).createFromSink(); + + //add content + for(int i = 0; i < 100; i++){ + sink.put(i, "Value " + Integer.toString(i)); + } + + sink.create(); + + //now open in read-only mode + Volume openVol = MappedFileVol.FACTORY.makeVolume(VOLUME_LOCATION, true); + + SortedTableMap sortedTableMap = SortedTableMap.open( + openVol, + Serializer.INTEGER, + Serializer.STRING + ); + + assertEquals(100, sortedTableMap.size()); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/mapdb/TransactionsUnitTest.java b/libraries-2/src/test/java/com/baeldung/mapdb/TransactionsUnitTest.java new file mode 100644 index 0000000000..4de9db10e8 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/mapdb/TransactionsUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.mapdb; + +import org.junit.Test; +import org.mapdb.DB; +import org.mapdb.DBMaker; +import org.mapdb.Serializer; + +import java.util.NavigableSet; + +import static junit.framework.Assert.assertEquals; + +public class TransactionsUnitTest { + + @Test + public void givenValidDBSetup_whenTransactionCommittedAndRolledBack_checkPreviousStateAchieved() { + + DB db = DBMaker.memoryDB().transactionEnable().make(); + + NavigableSet set = db + .treeSet("mySet") + .serializer(Serializer.STRING) + .createOrOpen(); + + set.add("One"); + set.add("Two"); + + db.commit(); + + assertEquals(2, set.size()); + + set.add("Three"); + + assertEquals(3, set.size()); + + db.rollback(); + + assertEquals(2, set.size()); + + db.close(); + } +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java b/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java new file mode 100644 index 0000000000..1e3b183aa7 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java @@ -0,0 +1,9 @@ +package com.baeldung.matrices; + +public class MatrixMultiplicationBenchmarking { + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java new file mode 100644 index 0000000000..05944e7b3a --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.matrices.apache; + +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.RealMatrix; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class RealMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + RealMatrix firstMatrix = new Array2DRowRealMatrix( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + RealMatrix secondMatrix = new Array2DRowRealMatrix( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + RealMatrix expected = new Array2DRowRealMatrix( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + RealMatrix actual = firstMatrix.multiply(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java new file mode 100644 index 0000000000..fb4a419eb0 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.matrices.colt; + +import cern.colt.matrix.DoubleFactory2D; +import cern.colt.matrix.DoubleMatrix2D; +import cern.colt.matrix.linalg.Algebra; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class DoubleMatrix2DUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + DoubleFactory2D doubleFactory2D = DoubleFactory2D.dense; + + DoubleMatrix2D firstMatrix = doubleFactory2D.make( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + DoubleMatrix2D secondMatrix = doubleFactory2D.make( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + DoubleMatrix2D expected = doubleFactory2D.make( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + Algebra algebra = new Algebra(); + DoubleMatrix2D actual = algebra.mult(firstMatrix, secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java new file mode 100644 index 0000000000..b025266a1d --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.matrices.ejml; + +import org.ejml.simple.SimpleMatrix; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class SimpleMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + SimpleMatrix firstMatrix = new SimpleMatrix( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + SimpleMatrix secondMatrix = new SimpleMatrix( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + SimpleMatrix expected = new SimpleMatrix( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + SimpleMatrix actual = firstMatrix.mult(secondMatrix); + + assertThat(actual).matches(m -> m.isIdentical(expected, 0d)); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java new file mode 100644 index 0000000000..be9e483d5b --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.matrices.homemade; + +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class HomemadeMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + double[][] firstMatrix = { + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + }; + + double[][] secondMatrix = { + new double[]{1d, 2d, 3d, 7d}, + new double[]{5d, 2d, 8d, 1d} + }; + + double[][] expected = { + new double[]{26d, 12d, 43d, 12d}, + new double[]{17d, 10d, 30d, 17d}, + new double[]{36d, 16d, 59d, 14d} + }; + + double[][] actual = multiplyMatrices(firstMatrix, secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + + private double[][] multiplyMatrices(double[][] firstMatrix, double[][] secondMatrix) { + double[][] result = new double[firstMatrix.length][secondMatrix[0].length]; + + for (int row = 0; row < result.length; row++) { + for (int col = 0; col < result[row].length; col++) { + result[row][col] = multiplyMatricesCell(firstMatrix, secondMatrix, row, col); + } + } + + return result; + } + + private double multiplyMatricesCell(double[][] firstMatrix, double[][] secondMatrix, int row, int col) { + double cell = 0; + for (int i = 0; i < secondMatrix.length; i++) { + cell += firstMatrix[row][i] * secondMatrix[i][col]; + } + return cell; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java new file mode 100644 index 0000000000..afb84ff3db --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.matrices.la4j; + +import org.junit.jupiter.api.Test; +import org.la4j.Matrix; +import org.la4j.matrix.dense.Basic2DMatrix; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class Basic2DMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + Matrix firstMatrix = new Basic2DMatrix( + new double[][]{ + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + } + ); + + Matrix secondMatrix = new Basic2DMatrix( + new double[][]{ + new double[]{1d, 2d, 3d, 7d}, + new double[]{5d, 2d, 8d, 1d} + } + ); + + Matrix expected = new Basic2DMatrix( + new double[][]{ + new double[]{26d, 12d, 43d, 12d}, + new double[]{17d, 10d, 30d, 17d}, + new double[]{36d, 16d, 59d, 14d} + } + ); + + Matrix actual = firstMatrix.multiply(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java new file mode 100644 index 0000000000..fb3030bccf --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.matrices.nd4j; + +import org.junit.jupiter.api.Test; +import org.nd4j.linalg.api.ndarray.INDArray; +import org.nd4j.linalg.factory.Nd4j; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class INDArrayUnitTest { + + @Test + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + INDArray firstMatrix = Nd4j.create( + new double[][]{ + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + } + ); + + INDArray secondMatrix = Nd4j.create( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + INDArray expected = Nd4j.create( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + INDArray actual = firstMatrix.mmul(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java b/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java new file mode 100644 index 0000000000..11a295031a --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java @@ -0,0 +1,102 @@ +package com.baeldung.okhttp; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.ResponseBody; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.InputStreamReader; + +public class ResponseDecoderUnitTest { + + @Rule public ExpectedException exceptionRule = ExpectedException.none(); + + @Rule public MockWebServer server = new MockWebServer(); + + SimpleEntity sampleResponse; + + MockResponse mockResponse; + + OkHttpClient client; + + @Before + public void setUp() { + sampleResponse = new SimpleEntity("Baeldung"); + client = new OkHttpClient.Builder().build(); + mockResponse = new MockResponse() + .setResponseCode(200) + .setHeader("Content-Type", "application/json") + .setBody(new Gson().toJson(sampleResponse)); + } + + @Test + public void givenJacksonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + Assert.assertNotEquals(0, responseBody.contentLength()); + + ObjectMapper objectMapper = new ObjectMapper(); + SimpleEntity entity = objectMapper.readValue(responseBody.string(), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + + @Test + public void givenGsonDecoder_whenGetByteStreamOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + Assert.assertNotEquals(0, responseBody.contentLength()); + + Gson gson = new Gson(); + SimpleEntity entity = gson.fromJson(new InputStreamReader(responseBody.byteStream()), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + + @Test + public void givenGsonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + + Gson gson = new Gson(); + SimpleEntity entity = gson.fromJson(responseBody.string(), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java b/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java new file mode 100644 index 0000000000..211e43e556 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java @@ -0,0 +1,22 @@ +package com.baeldung.okhttp; + +public class SimpleEntity { + protected String name; + + public SimpleEntity(String name) { + this.name = name; + } + + //no-arg constructor, getters and setters here + + public SimpleEntity() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsUnitTest.java b/libraries-2/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsUnitTest.java new file mode 100644 index 0000000000..adc753a8ad --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/parallel_collectors/ParallelCollectorsUnitTest.java @@ -0,0 +1,168 @@ +package com.baeldung.parallel_collectors; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +import static com.pivovarit.collectors.ParallelCollectors.parallel; +import static com.pivovarit.collectors.ParallelCollectors.parallelOrdered; +import static com.pivovarit.collectors.ParallelCollectors.parallelToCollection; +import static com.pivovarit.collectors.ParallelCollectors.parallelToList; +import static com.pivovarit.collectors.ParallelCollectors.parallelToMap; +import static com.pivovarit.collectors.ParallelCollectors.parallelToStream; + +public class ParallelCollectorsUnitTest { + + @Test + public void shouldProcessInParallelWithStreams() { + List ids = Arrays.asList(1, 2, 3); + + List results = ids.parallelStream() + .map(i -> fetchById(i)) + .collect(Collectors.toList()); + + System.out.println(results); + } + + @Test + public void shouldProcessInParallelWithParallelCollectors() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + CompletableFuture> results = ids.stream() + .collect(parallelToList(i -> fetchById(i), executor, 4)); + + System.out.println(results.join()); + } + + @Test + public void shouldCollectToList() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + List results = ids.stream() + .collect(parallelToList(i -> fetchById(i), executor, 4)) + .join(); + + System.out.println(results); // [user-1, user-2, user-3] + } + + @Test + public void shouldCollectToCollection() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + List results = ids.stream() + .collect(parallelToCollection(i -> fetchById(i), LinkedList::new, executor, 4)) + .join(); + + System.out.println(results); // [user-1, user-2, user-3] + } + + @Test + public void shouldCollectToStream() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + Map> results = ids.stream() + .collect(parallelToStream(i -> fetchById(i), executor, 4)) + .thenApply(stream -> stream.collect(Collectors.groupingBy(i -> i.length()))) + .join(); + + System.out.println(results); // [user-1, user-2, user-3] + } + + @Test + public void shouldStreamInCompletionOrder() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + ids.stream() + .collect(parallel(i -> fetchByIdWithRandomDelay(i), executor, 4)) + .forEach(System.out::println); + } + + @Test + public void shouldStreamInOriginalOrder() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + ids.stream() + .collect(parallelOrdered(i -> fetchByIdWithRandomDelay(i), executor, 4)) + .forEach(System.out::println); + } + + @Test + public void shouldCollectToMap() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + Map results = ids.stream() + .collect(parallelToMap(i -> i, i -> fetchById(i), executor, 4)) + .join(); + + System.out.println(results); // {1=user-1, 2=user-2, 3=user-3} + } + + @Test + public void shouldCollectToTreeMap() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + Map results = ids.stream() + .collect(parallelToMap(i -> i, i -> fetchById(i), TreeMap::new, executor, 4)) + .join(); + + System.out.println(results); // {1=user-1, 2=user-2, 3=user-3} + } + + @Test + public void shouldCollectToTreeMapAndResolveClashes() { + ExecutorService executor = Executors.newFixedThreadPool(10); + + List ids = Arrays.asList(1, 2, 3); + + Map results = ids.stream() + .collect(parallelToMap(i -> i, i -> fetchById(i), TreeMap::new, (s1, s2) -> s1, executor, 4)) + .join(); + + System.out.println(results); // {1=user-1, 2=user-2, 3=user-3} + } + + private static String fetchById(int id) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // ignore shamelessly + } + + return "user-" + id; + } + + private static String fetchByIdWithRandomDelay(int id) { + try { + Thread.sleep(ThreadLocalRandom.current().nextInt(1000)); + } catch (InterruptedException e) { + // ignore shamelessly + } + + return "user-" + id; + } +} diff --git a/libraries-2/src/test/resources/classgraph/my.config b/libraries-2/src/test/resources/classgraph/my.config new file mode 100644 index 0000000000..b99df573f6 --- /dev/null +++ b/libraries-2/src/test/resources/classgraph/my.config @@ -0,0 +1 @@ +my data \ No newline at end of file diff --git a/libraries-2/src/test/resources/greeting.hbs b/libraries-2/src/test/resources/greeting.hbs new file mode 100644 index 0000000000..71a8266bce --- /dev/null +++ b/libraries-2/src/test/resources/greeting.hbs @@ -0,0 +1 @@ +Hi {{name}}! \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/each.html b/libraries-2/src/test/resources/handlebars/each.html new file mode 100644 index 0000000000..1570311bfc --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/each.html @@ -0,0 +1,3 @@ +{{#each friends}} +{{name}} is my friend. +{{/each}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/each_mustache.html b/libraries-2/src/test/resources/handlebars/each_mustache.html new file mode 100644 index 0000000000..1570311bfc --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/each_mustache.html @@ -0,0 +1,3 @@ +{{#each friends}} +{{name}} is my friend. +{{/each}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/greeting.html b/libraries-2/src/test/resources/handlebars/greeting.html new file mode 100644 index 0000000000..71a8266bce --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/greeting.html @@ -0,0 +1 @@ +Hi {{name}}! \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/header.html b/libraries-2/src/test/resources/handlebars/header.html new file mode 100644 index 0000000000..80cca699e4 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/header.html @@ -0,0 +1 @@ +

Hi {{name}}!

\ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/if.html b/libraries-2/src/test/resources/handlebars/if.html new file mode 100644 index 0000000000..ebdc724f66 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/if.html @@ -0,0 +1,5 @@ +{{#if busy}} +

{{name}} is busy.

+{{else}} +

{{name}} is not busy.

+{{/if}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/if_mustache.html b/libraries-2/src/test/resources/handlebars/if_mustache.html new file mode 100644 index 0000000000..d75f5fa8f9 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/if_mustache.html @@ -0,0 +1,5 @@ +{{#if busy}} +

{{name}} is busy.

+{{^}} +

{{name}} is not busy.

+{{/if}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/messagebase.html b/libraries-2/src/test/resources/handlebars/messagebase.html new file mode 100644 index 0000000000..7ee3257e06 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/messagebase.html @@ -0,0 +1,9 @@ + + +{{#block "intro"}} + This is the intro +{{/block}} +{{#block "message"}} +{{/block}} + + \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/page.html b/libraries-2/src/test/resources/handlebars/page.html new file mode 100644 index 0000000000..27b20737f3 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/page.html @@ -0,0 +1,2 @@ +{{>header}} +

This is the page {{name}}

\ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/person.html b/libraries-2/src/test/resources/handlebars/person.html new file mode 100644 index 0000000000..9df7850f60 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/person.html @@ -0,0 +1 @@ +{{#isBusy this}}{{/isBusy}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/simplemessage.html b/libraries-2/src/test/resources/handlebars/simplemessage.html new file mode 100644 index 0000000000..3b3a01980a --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/simplemessage.html @@ -0,0 +1,4 @@ +{{#partial "message" }} + Hi there! +{{/partial}} +{{> messagebase}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/with.html b/libraries-2/src/test/resources/handlebars/with.html new file mode 100644 index 0000000000..90077b4835 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/with.html @@ -0,0 +1,3 @@ +{{#with address}} +

I live in {{street}}

+{{/with}} \ No newline at end of file diff --git a/libraries-2/src/test/resources/handlebars/with_mustache.html b/libraries-2/src/test/resources/handlebars/with_mustache.html new file mode 100644 index 0000000000..3adf6a7556 --- /dev/null +++ b/libraries-2/src/test/resources/handlebars/with_mustache.html @@ -0,0 +1,3 @@ +{{#address}} +

I live in {{street}}

+{{/address}} \ No newline at end of file diff --git a/libraries-apache-commons/pom.xml b/libraries-apache-commons/pom.xml index c7ff918af9..cb5990df22 100644 --- a/libraries-apache-commons/pom.xml +++ b/libraries-apache-commons/pom.xml @@ -95,14 +95,11 @@ 3.6.2 2.5 1.6 - 1.4.196 4.1 - 4.12 2.0.0.0 1.10.L001 3.5.2 3.6 - 1.3 3.6.1
diff --git a/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java b/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java index 538fa3accb..2c7644fd64 100644 --- a/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java +++ b/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java @@ -29,6 +29,6 @@ public class CourseService { } public static void copyProperties(Course course, CourseEntity courseEntity) throws IllegalAccessException, InvocationTargetException { - BeanUtils.copyProperties(course, courseEntity); + BeanUtils.copyProperties(courseEntity, course); } } diff --git a/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java b/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java index 833d91b2c4..224ee8404c 100644 --- a/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java +++ b/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java @@ -44,6 +44,8 @@ public class CourseServiceUnitTest { CourseEntity courseEntity = new CourseEntity(); CourseService.copyProperties(course, courseEntity); + Assert.assertNotNull(course.getName()); + Assert.assertNotNull(courseEntity.getName()); Assert.assertEquals(course.getName(), courseEntity.getName()); Assert.assertEquals(course.getCodes(), courseEntity.getCodes()); Assert.assertNull(courseEntity.getStudent("ST-1")); diff --git a/libraries-data/README.md b/libraries-data/README.md index 69856af66b..077961f887 100644 --- a/libraries-data/README.md +++ b/libraries-data/README.md @@ -15,3 +15,4 @@ - [Intro to Apache Storm](https://www.baeldung.com/apache-storm) - [Guide to Ebean ORM](https://www.baeldung.com/ebean-orm) - [Introduction to Kafka Connectors](https://www.baeldung.com/kafka-connectors-guide) +- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb) diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index 54d24edbf6..31aaaea951 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -263,6 +263,16 @@ org.apache.storm storm-core ${storm.version} + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + log4j-over-slf4j + + @@ -429,27 +439,17 @@ - - - Apache Staging - https://repository.apache.org/content/groups/staging - - - 1.2.2 4.0.1 - 1.4.196 16.5.1 - 4.12 - 3.7.0 5.0 1.0.0 2.4.0 2.8.2 1.1.0 1.5.0 - 2.8.5 + 2.9.7 3.0.0 3.6.2 3.8.4 diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties b/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties deleted file mode 100644 index 5b91baddbd..0000000000 --- a/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties +++ /dev/null @@ -1,88 +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. -## - -# This file contains some of the configurations for the Kafka Connect distributed worker. This file is intended -# to be used with the examples, and some settings may differ from those used in a production system, especially -# the `bootstrap.servers` and those specifying replication factors. - -# A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. -bootstrap.servers=localhost:9092 - -# unique name for the cluster, used in forming the Connect cluster group. Note that this must not conflict with consumer group IDs -group.id=connect-cluster - -# The converters specify the format of data in Kafka and how to translate it into Connect data. Every Connect user will -# need to configure these based on the format they want their data in when loaded from or stored into Kafka -key.converter=org.apache.kafka.connect.json.JsonConverter -value.converter=org.apache.kafka.connect.json.JsonConverter -# Converter-specific settings can be passed in by prefixing the Converter's setting with the converter we want to apply -# it to -key.converter.schemas.enable=true -value.converter.schemas.enable=true - -# Topic to use for storing offsets. This topic should have many partitions and be replicated and compacted. -# Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create -# the topic before starting Kafka Connect if a specific topic configuration is needed. -# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value. -# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able -# to run this example on a single-broker cluster and so here we instead set the replication factor to 1. -offset.storage.topic=connect-offsets -offset.storage.replication.factor=1 -#offset.storage.partitions=25 - -# Topic to use for storing connector and task configurations; note that this should be a single partition, highly replicated, -# and compacted topic. Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create -# the topic before starting Kafka Connect if a specific topic configuration is needed. -# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value. -# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able -# to run this example on a single-broker cluster and so here we instead set the replication factor to 1. -config.storage.topic=connect-configs -config.storage.replication.factor=1 - -# Topic to use for storing statuses. This topic can have multiple partitions and should be replicated and compacted. -# Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create -# the topic before starting Kafka Connect if a specific topic configuration is needed. -# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value. -# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able -# to run this example on a single-broker cluster and so here we instead set the replication factor to 1. -status.storage.topic=connect-status -status.storage.replication.factor=1 -#status.storage.partitions=5 - -# Flush much faster than normal, which is useful for testing/debugging -offset.flush.interval.ms=10000 - -# These are provided to inform the user about the presence of the REST host and port configs -# Hostname & Port for the REST API to listen on. If this is set, it will bind to the interface used to listen to requests. -#rest.host.name= -#rest.port=8083 - -# The Hostname & Port that will be given out to other workers to connect to i.e. URLs that are routable from other servers. -#rest.advertised.host.name= -#rest.advertised.port= - -# Set to a list of filesystem paths separated by commas (,) to enable class loading isolation for plugins -# (connectors, converters, transformations). The list should consist of top level directories that include -# any combination of: -# a) directories immediately containing jars with plugins and their dependencies -# b) uber-jars with plugins and their dependencies -# c) directories immediately containing the package directory structure of classes of plugins and their dependencies -# Examples: -# plugin.path=/usr/local/share/java,/usr/local/share/kafka/plugins,/opt/connectors, -# Replace the relative path below with an absolute path if you are planning to start Kafka Connect from within a -# directory other than the home directory of Confluent Platform. -plugin.path=./share/java diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json b/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json index 333768e4b7..852f400fc6 100644 --- a/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json +++ b/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json @@ -1,22 +1,14 @@ { - "firstName": "John", - "lastName": "Smith", - "age": 25, - "address": { - "streetAddress": "21 2nd Street", - "city": "New York", - "state": "NY", - "postalCode": "10021" - }, - "phoneNumber": [{ - "type": "home", - "number": "212 555-1234" - }, { - "type": "fax", - "number": "646 555-4567" - } - ], - "gender": { - "type": "male" + "name": "mongodb-sink", + "config": { + "connector.class": "at.grahsl.kafka.connect.mongodb.MongoDbSinkConnector", + "tasks.max": 1, + "topics": "connect-custom", + "mongodb.connection.uri": "mongodb://mongo-db/test?retryWrites=true", + "mongodb.collection": "MyCollection", + "key.converter": "org.apache.kafka.connect.json.JsonConverter", + "key.converter.schemas.enable": false, + "value.converter": "org.apache.kafka.connect.json.JsonConverter", + "value.converter.schemas.enable": false } } diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json b/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json index 02d87c5ad7..c76d326c0a 100644 --- a/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json +++ b/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json @@ -3,9 +3,11 @@ "config": { "connector.class": "io.confluent.connect.mqtt.MqttSourceConnector", "tasks.max": 1, - "mqtt.server.uri": "ws://broker.hivemq.com:8000/mqtt", + "mqtt.server.uri": "tcp://mosquitto:1883", "mqtt.topics": "baeldung", "kafka.topic": "connect-custom", - "value.converter": "org.apache.kafka.connect.converters.ByteArrayConverter" + "value.converter": "org.apache.kafka.connect.converters.ByteArrayConverter", + "confluent.topic.bootstrap.servers": "kafka:9092", + "confluent.topic.replication.factor": 1 } -} +} \ No newline at end of file diff --git a/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml b/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml new file mode 100644 index 0000000000..26cd653335 --- /dev/null +++ b/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml @@ -0,0 +1,94 @@ +version: '3.3' + +services: + mosquitto: + image: eclipse-mosquitto:1.5.5 + hostname: mosquitto + container_name: mosquitto + expose: + - "1883" + ports: + - "1883:1883" + zookeeper: + image: zookeeper:3.4.9 + restart: unless-stopped + hostname: zookeeper + container_name: zookeeper + ports: + - "2181:2181" + environment: + ZOO_MY_ID: 1 + ZOO_PORT: 2181 + ZOO_SERVERS: server.1=zookeeper:2888:3888 + volumes: + - ./zookeeper/data:/data + - ./zookeeper/datalog:/datalog + kafka: + image: confluentinc/cp-kafka:5.1.0 + hostname: kafka + container_name: kafka + ports: + - "9092:9092" + environment: + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 + KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" + KAFKA_BROKER_ID: 1 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + volumes: + - ./kafka/data:/var/lib/kafka/data + depends_on: + - zookeeper + kafka-connect: + image: confluentinc/cp-kafka-connect:5.1.0 + hostname: kafka-connect + container_name: kafka-connect + ports: + - "8083:8083" + environment: + CONNECT_BOOTSTRAP_SERVERS: "kafka:9092" + CONNECT_REST_ADVERTISED_HOST_NAME: connect + CONNECT_REST_PORT: 8083 + CONNECT_GROUP_ID: compose-connect-group + CONNECT_CONFIG_STORAGE_TOPIC: docker-connect-configs + CONNECT_OFFSET_STORAGE_TOPIC: docker-connect-offsets + CONNECT_STATUS_STORAGE_TOPIC: docker-connect-status + CONNECT_KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter + CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter + CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter" + CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter" + CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: "1" + CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: "1" + CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: "1" + CONNECT_PLUGIN_PATH: '/usr/share/java,/etc/kafka-connect/jars' + CONNECT_CONFLUENT_TOPIC_REPLICATION_FACTOR: 1 + volumes: + - /tmp/custom/jars:/etc/kafka-connect/jars + depends_on: + - zookeeper + - kafka + - mosquitto + mongo-db: + image: mongo:4.0.5 + hostname: mongo-db + container_name: mongo-db + expose: + - "27017" + ports: + - "27017:27017" + command: --bind_ip_all --smallfiles + volumes: + - ./mongo-db:/data + mongoclient: + image: mongoclient/mongoclient:2.2.0 + container_name: mongoclient + hostname: mongoclient + depends_on: + - mongo-db + ports: + - 3000:3000 + environment: + MONGO_URL: "mongodb://mongo-db:27017" + PORT: 3000 + expose: + - "3000" \ No newline at end of file diff --git a/libraries-data/src/main/resources/logback.xml b/libraries-data/src/main/resources/logback.xml index a57d22fcb2..3d2ec51566 100644 --- a/libraries-data/src/main/resources/logback.xml +++ b/libraries-data/src/main/resources/logback.xml @@ -9,7 +9,7 @@ - + \ No newline at end of file diff --git a/libraries-data/src/test/java/com/baeldung/flink/BackupCreatorIntegrationTest.java b/libraries-data/src/test/java/com/baeldung/flink/BackupCreatorIntegrationTest.java index ab7d119c16..f46fffbb59 100644 --- a/libraries-data/src/test/java/com/baeldung/flink/BackupCreatorIntegrationTest.java +++ b/libraries-data/src/test/java/com/baeldung/flink/BackupCreatorIntegrationTest.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; public class BackupCreatorIntegrationTest { @@ -88,7 +89,7 @@ public class BackupCreatorIntegrationTest { SerializationSchema serializationSchema = new BackupSerializationSchema(); byte[] backupProcessed = serializationSchema.serialize(backup); - assertEquals(backupSerialized, backupProcessed); + assertArrayEquals(backupSerialized, backupProcessed); } private static class CollectingSink implements SinkFunction { diff --git a/libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java b/libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java index 96ed090482..9db7bdb4ac 100644 --- a/libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java +++ b/libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java @@ -15,100 +15,88 @@ import com.googlecode.jmapper.api.JMapperAPI; public class JMapperIntegrationTest { - @Test - public void givenUser_whenUseAnnotation_thenConverted(){ + public void givenUser_whenUseAnnotation_thenConverted() { JMapper userMapper = new JMapper<>(UserDto.class, User.class); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); UserDto result = userMapper.getDestination(user); - System.out.println(result); - assertEquals(user.getId(), result.getId()); - assertEquals(user.getEmail(), result.getUsername()); - } - - @Test - public void givenUser_whenUseGlobalMapAnnotation_thenConverted(){ - JMapper userMapper= new JMapper<>(UserDto1.class, User.class); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto1 result = userMapper.getDestination(user); - - System.out.println(result); - assertEquals(user.getId(), result.getId()); - assertEquals(user.getEmail(), result.getEmail()); - } - - @Test - public void givenUser_whenUseAnnotationExplicitConversion_thenConverted(){ - JMapper userMapper = new JMapper<>(UserDto.class, User.class); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto result = userMapper.getDestination(user); - - System.out.println(result); - assertEquals(user.getId(), result.getId()); - assertEquals(user.getEmail(), result.getUsername()); - assertTrue(result.getAge() > 0); - } - - //======================= XML - - @Test - public void givenUser_whenUseXml_thenConverted(){ - JMapper userMapper = new JMapper<>(UserDto.class, User.class,"user_jmapper.xml"); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto result = userMapper.getDestination(user); - - System.out.println(result); - assertEquals(user.getId(), result.getId()); - assertEquals(user.getEmail(), result.getUsername()); - } - - @Test - public void givenUser_whenUseXmlGlobal_thenConverted(){ - JMapper userMapper = new JMapper<>(UserDto1.class, User.class,"user_jmapper1.xml"); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto1 result = userMapper.getDestination(user); - - System.out.println(result); - assertEquals(user.getId(), result.getId()); - assertEquals(user.getEmail(), result.getEmail()); - } - - // ===== API - - @Test - public void givenUser_whenUseApi_thenConverted(){ - JMapperAPI jmapperApi = new JMapperAPI() .add(mappedClass(UserDto.class) - .add(attribute("id").value("id")) - .add(attribute("username").value("email")) - ) ; - JMapper userMapper = new JMapper<>(UserDto.class, User.class, jmapperApi); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto result = userMapper.getDestination(user); - - System.out.println(result); assertEquals(user.getId(), result.getId()); assertEquals(user.getEmail(), result.getUsername()); } - - @Test - public void givenUser_whenUseApiGlobal_thenConverted(){ - JMapperAPI jmapperApi = new JMapperAPI() .add(mappedClass(UserDto.class) - .add(global()) - ) ; - JMapper userMapper1 = new JMapper<>(UserDto1.class, User.class,jmapperApi); - - User user = new User(1L,"john@test.com", LocalDate.of(1980,8,20)); - UserDto1 result = userMapper1.getDestination(user); - System.out.println(result); + @Test + public void givenUser_whenUseGlobalMapAnnotation_thenConverted() { + JMapper userMapper = new JMapper<>(UserDto1.class, User.class); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto1 result = userMapper.getDestination(user); + assertEquals(user.getId(), result.getId()); assertEquals(user.getEmail(), result.getEmail()); } + + @Test + public void givenUser_whenUseAnnotationExplicitConversion_thenConverted() { + JMapper userMapper = new JMapper<>(UserDto.class, User.class); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto result = userMapper.getDestination(user); + + assertEquals(user.getId(), result.getId()); + assertEquals(user.getEmail(), result.getUsername()); + assertTrue(result.getAge() > 0); + } + + // ======================= XML + + @Test + public void givenUser_whenUseXml_thenConverted() { + JMapper userMapper = new JMapper<>(UserDto.class, User.class, "user_jmapper.xml"); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto result = userMapper.getDestination(user); + + assertEquals(user.getId(), result.getId()); + assertEquals(user.getEmail(), result.getUsername()); + } + + @Test + public void givenUser_whenUseXmlGlobal_thenConverted() { + JMapper userMapper = new JMapper<>(UserDto1.class, User.class, "user_jmapper1.xml"); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto1 result = userMapper.getDestination(user); + + assertEquals(user.getId(), result.getId()); + assertEquals(user.getEmail(), result.getEmail()); + } + + // ===== API + + @Test + public void givenUser_whenUseApi_thenConverted() { + JMapperAPI jmapperApi = new JMapperAPI().add(mappedClass(UserDto.class).add(attribute("id").value("id")).add(attribute("username").value("email"))); + JMapper userMapper = new JMapper<>(UserDto.class, User.class, jmapperApi); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto result = userMapper.getDestination(user); + + assertEquals(user.getId(), result.getId()); + assertEquals(user.getEmail(), result.getUsername()); + } + + @Test + public void givenUser_whenUseApiGlobal_thenConverted() { + JMapperAPI jmapperApi = new JMapperAPI().add(mappedClass(UserDto.class).add(global())); + JMapper userMapper1 = new JMapper<>(UserDto1.class, User.class, jmapperApi); + + User user = new User(1L, "john@test.com", LocalDate.of(1980, 8, 20)); + UserDto1 result = userMapper1.getDestination(user); + + assertEquals(user.getId(), result.getId()); + assertEquals(user.getEmail(), result.getEmail()); + } + } diff --git a/libraries-http/README.md b/libraries-http/README.md new file mode 100644 index 0000000000..dd8c6a5f67 --- /dev/null +++ b/libraries-http/README.md @@ -0,0 +1,7 @@ + +### Relevant Articles: + +- [A Guide to OkHttp](http://www.baeldung.com/guide-to-okhttp) +- [A Guide to Google-Http-Client](http://www.baeldung.com/google-http-client) +- [Asynchronous HTTP with async-http-client in Java](http://www.baeldung.com/async-http-client) +- [WebSockets with AsyncHttpClient](http://www.baeldung.com/async-http-client-websockets) diff --git a/libraries-http/pom.xml b/libraries-http/pom.xml new file mode 100644 index 0000000000..6006a93aef --- /dev/null +++ b/libraries-http/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + libraries-http + libraries-http + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.assertj + assertj-core + ${assertj.version} + + + + + com.squareup.okhttp3 + okhttp + ${com.squareup.okhttp3.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.asynchttpclient + async-http-client + ${async.http.client.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + com.google.code.gson + gson + 2.8.5 + + + + com.squareup.okhttp3 + mockwebserver + ${com.squareup.okhttp3.version} + test + + + + + + 3.6.2 + 3.14.2 + 1.23.0 + 2.2.0 + + diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/GitHubExample.java b/libraries-http/src/main/java/com/baeldung/googlehttpclientguide/GitHubExample.java similarity index 100% rename from libraries/src/main/java/com/baeldung/googlehttpclientguide/GitHubExample.java rename to libraries-http/src/main/java/com/baeldung/googlehttpclientguide/GitHubExample.java diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/GitHubUrl.java b/libraries-http/src/main/java/com/baeldung/googlehttpclientguide/GitHubUrl.java similarity index 100% rename from libraries/src/main/java/com/baeldung/googlehttpclientguide/GitHubUrl.java rename to libraries-http/src/main/java/com/baeldung/googlehttpclientguide/GitHubUrl.java diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/User.java b/libraries-http/src/main/java/com/baeldung/googlehttpclientguide/User.java similarity index 100% rename from libraries/src/main/java/com/baeldung/googlehttpclientguide/User.java rename to libraries-http/src/main/java/com/baeldung/googlehttpclientguide/User.java diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/logging.properties b/libraries-http/src/main/java/com/baeldung/googlehttpclientguide/logging.properties similarity index 100% rename from libraries/src/main/java/com/baeldung/googlehttpclientguide/logging.properties rename to libraries-http/src/main/java/com/baeldung/googlehttpclientguide/logging.properties diff --git a/libraries-http/src/main/resources/logback.xml b/libraries-http/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/libraries-http/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/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientLiveTest.java b/libraries-http/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientLiveTest.java rename to libraries-http/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientLiveTest.java diff --git a/spring-rest/src/test/java/com/baeldung/client/Consts.java b/libraries-http/src/test/java/com/baeldung/client/Consts.java similarity index 100% rename from spring-rest/src/test/java/com/baeldung/client/Consts.java rename to libraries-http/src/test/java/com/baeldung/client/Consts.java diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/DefaultContentTypeInterceptor.java b/libraries-http/src/test/java/com/baeldung/okhttp/DefaultContentTypeInterceptor.java similarity index 100% rename from spring-rest/src/test/java/com/baeldung/okhttp/DefaultContentTypeInterceptor.java rename to libraries-http/src/test/java/com/baeldung/okhttp/DefaultContentTypeInterceptor.java diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java similarity index 93% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java index 75980a5360..7b28c17607 100644 --- a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java +++ b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpFileUploadingLiveTest.java @@ -19,6 +19,9 @@ import okhttp3.Response; import org.junit.Before; import org.junit.Test; +/** + * Execute spring-rest module before running this live test + */ public class OkHttpFileUploadingLiveTest { private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-rest"; diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java similarity index 93% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java index 3edd2eab06..5efc4aa998 100644 --- a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java +++ b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpGetLiveTest.java @@ -17,6 +17,9 @@ import okhttp3.Response; import org.junit.Before; import org.junit.Test; +/** + * Execute spring-rest module before running this live test + */ public class OkHttpGetLiveTest { private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-rest"; diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpHeaderLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpHeaderLiveTest.java similarity index 100% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpHeaderLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpHeaderLiveTest.java diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java similarity index 95% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java index 207ad14e71..24617794d1 100644 --- a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java +++ b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpMiscLiveTest.java @@ -20,6 +20,9 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Execute spring-rest module before running this live test + */ public class OkHttpMiscLiveTest { private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-rest"; diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java similarity index 94% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java index 66fee0b626..19e689c093 100644 --- a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java +++ b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpPostingLiveTest.java @@ -20,6 +20,9 @@ import okhttp3.Response; import org.junit.Before; import org.junit.Test; +/** + * Execute spring-rest module before running this live test + */ public class OkHttpPostingLiveTest { private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-rest"; diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/OkHttpRedirectLiveTest.java b/libraries-http/src/test/java/com/baeldung/okhttp/OkHttpRedirectLiveTest.java similarity index 100% rename from spring-rest/src/test/java/com/baeldung/okhttp/OkHttpRedirectLiveTest.java rename to libraries-http/src/test/java/com/baeldung/okhttp/OkHttpRedirectLiveTest.java diff --git a/spring-rest/src/test/java/com/baeldung/okhttp/ProgressRequestWrapper.java b/libraries-http/src/test/java/com/baeldung/okhttp/ProgressRequestWrapper.java similarity index 100% rename from spring-rest/src/test/java/com/baeldung/okhttp/ProgressRequestWrapper.java rename to libraries-http/src/test/java/com/baeldung/okhttp/ProgressRequestWrapper.java diff --git a/libraries-primitive/README.MD b/libraries-primitive/README.MD new file mode 100644 index 0000000000..f27fb73dd6 --- /dev/null +++ b/libraries-primitive/README.MD @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Guide to FastUtil](https://www.baeldung.com/fastutil) diff --git a/libraries-primitive/pom.xml b/libraries-primitive/pom.xml new file mode 100644 index 0000000000..9bb58470b2 --- /dev/null +++ b/libraries-primitive/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.baeldung + libraries-primitive + 1.0-SNAPSHOT + + + + + it.unimi.dsi + fastutil + 8.2.2 + + + + junit + junit + 4.12 + test + + + + org.openjdk.jmh + jmh-core + 1.19 + test + + + org.openjdk.jmh + jmh-generator-annprocess + 1.19 + test + + + diff --git a/libraries-primitive/src/test/java/com/baeldung/BigArraysUnitTest.java b/libraries-primitive/src/test/java/com/baeldung/BigArraysUnitTest.java new file mode 100644 index 0000000000..a794d1a2f6 --- /dev/null +++ b/libraries-primitive/src/test/java/com/baeldung/BigArraysUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung; + +import it.unimi.dsi.fastutil.ints.IntBigArrays; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class BigArraysUnitTest { + + @Test + public void givenValidAray_whenWrapped_checkAccessFromIntBigArraysMethodsCorrect() { + int[] oneDArray = new int[] { 2, 1, 5, 2, 1, 7 }; + int[][] twoDArray = IntBigArrays.wrap(oneDArray.clone()); + + int firstIndex = IntBigArrays.get(twoDArray, 0); + int lastIndex = IntBigArrays.get(twoDArray, IntBigArrays.length(twoDArray)-1); + + assertEquals(2, firstIndex); + assertEquals(7, lastIndex); + + } + +} diff --git a/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java b/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java new file mode 100644 index 0000000000..2c77989fe5 --- /dev/null +++ b/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; +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; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +public class FastUtilTypeSpecificBenchmarkUnitTest { + + @Param({"100", "1000", "10000", "100000"}) + public int setSize; + + @Benchmark + public IntSet givenFastUtilsIntSetWithInitialSizeSet_whenPopulated_checkTimeTaken() { + IntSet intSet = new IntOpenHashSet(setSize); + for(int i = 0; i < setSize; i++){ + intSet.add(i); + } + return intSet; + } + + + @Benchmark + public Set givenCollectionsHashSetWithInitialSizeSet_whenPopulated_checkTimeTaken() { + Set intSet = new HashSet(setSize); + for(int i = 0; i < setSize; i++){ + intSet.add(i); + } + return intSet; + } + + public static void main(String... args) throws RunnerException { + Options opts = new OptionsBuilder() + .include(".*") + .warmupIterations(1) + .measurementIterations(2) + .jvmArgs("-Xms2g", "-Xmx2g") + .shouldDoGC(true) + .forks(1) + .build(); + + new Runner(opts).run(); + } + + + + +} diff --git a/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java b/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java new file mode 100644 index 0000000000..61295cc6f1 --- /dev/null +++ b/libraries-primitive/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung; + +import it.unimi.dsi.fastutil.doubles.Double2DoubleMap; +import it.unimi.dsi.fastutil.doubles.Double2DoubleOpenHashMap; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + + +public class FastUtilTypeSpecificUnitTest { + + @Test + public void givenValidDouble2DoubleMap_whenContentsQueried_checkCorrect(){ + Double2DoubleMap d2dMap = new Double2DoubleOpenHashMap(); + d2dMap.put(2.0, 5.5); + d2dMap.put(3.0, 6.6); + assertEquals(5.5, d2dMap.get(2.0)); + } + +} diff --git a/libraries-security/README.md b/libraries-security/README.md index 6923e0474e..b9bbf11cdf 100644 --- a/libraries-security/README.md +++ b/libraries-security/README.md @@ -2,3 +2,4 @@ - [Guide to ScribeJava](https://www.baeldung.com/scribejava) - [Guide to Passay](https://www.baeldung.com/java-passay) +- [Guide to Google Tink](https://www.baeldung.com/google-tink) diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index 3077abc29c..17d57fe203 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -23,7 +23,7 @@ org.springframework.security.oauth spring-security-oauth2 - 2.3.3.RELEASE + ${spring-security-oauth2.version} @@ -32,6 +32,12 @@ ${scribejava.version} + + com.google.crypto.tink + tink + ${tink.version} + + junit junit @@ -41,21 +47,21 @@ org.passay passay - 1.3.1 + ${passay.version} org.cryptacular cryptacular - 1.2.2 + ${cryptacular.version} - - 4.12 2.0.4.RELEASE 5.6.0 + 2.3.3.RELEASE + 1.3.1 + 1.2.2 + 1.2.2 - - diff --git a/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java b/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java new file mode 100644 index 0000000000..b98c698016 --- /dev/null +++ b/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java @@ -0,0 +1,101 @@ +package com.baeldung.tink; + +import com.google.crypto.tink.*; +import com.google.crypto.tink.aead.AeadConfig; +import com.google.crypto.tink.aead.AeadFactory; +import com.google.crypto.tink.aead.AeadKeyTemplates; +import com.google.crypto.tink.config.TinkConfig; +import com.google.crypto.tink.hybrid.HybridDecryptFactory; +import com.google.crypto.tink.hybrid.HybridEncryptFactory; +import com.google.crypto.tink.hybrid.HybridKeyTemplates; +import com.google.crypto.tink.mac.MacFactory; +import com.google.crypto.tink.mac.MacKeyTemplates; +import com.google.crypto.tink.signature.PublicKeySignFactory; +import com.google.crypto.tink.signature.PublicKeyVerifyFactory; +import com.google.crypto.tink.signature.SignatureKeyTemplates; +import org.junit.Assert; +import org.junit.Test; + +import java.security.GeneralSecurityException; + +public class TinkUnitTest { + + private static final String PLAINTEXT = "BAELDUNG"; + private static final String DATA = "TINK"; + + @Test + public void givenPlaintext_whenEncryptWithAead_thenPlaintextIsEncrypted() throws GeneralSecurityException { + + AeadConfig.register(); + + KeysetHandle keysetHandle = KeysetHandle.generateNew( + AeadKeyTemplates.AES256_GCM); + + Aead aead = AeadFactory.getPrimitive(keysetHandle); + + byte[] ciphertext = aead.encrypt(PLAINTEXT.getBytes(), + DATA.getBytes()); + + Assert.assertNotEquals(PLAINTEXT, new String(ciphertext)); + } + + @Test + public void givenData_whenComputeMAC_thenVerifyMAC() throws GeneralSecurityException { + + TinkConfig.register(); + + KeysetHandle keysetHandle = KeysetHandle.generateNew( + MacKeyTemplates.HMAC_SHA256_128BITTAG); + + Mac mac = MacFactory.getPrimitive(keysetHandle); + + byte[] tag = mac.computeMac(DATA.getBytes()); + + mac.verifyMac(tag, DATA.getBytes()); + } + + @Test + public void givenData_whenSignData_thenVerifySignature() throws GeneralSecurityException { + + TinkConfig.register(); + + KeysetHandle privateKeysetHandle = KeysetHandle.generateNew( + SignatureKeyTemplates.ECDSA_P256); + + PublicKeySign signer = PublicKeySignFactory.getPrimitive(privateKeysetHandle); + + byte[] signature = signer.sign(DATA.getBytes()); + + KeysetHandle publicKeysetHandle = + privateKeysetHandle.getPublicKeysetHandle(); + + PublicKeyVerify verifier = PublicKeyVerifyFactory.getPrimitive(publicKeysetHandle); + + verifier.verify(signature, DATA.getBytes()); + } + + @Test + public void givenPlaintext_whenEncryptWithHybridEncryption_thenVerifyDecryptedIsEqual() throws GeneralSecurityException { + + TinkConfig.register(); + + KeysetHandle privateKeysetHandle = KeysetHandle.generateNew( + HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256); + + KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle(); + + HybridEncrypt hybridEncrypt = HybridEncryptFactory.getPrimitive(publicKeysetHandle); + + HybridDecrypt hybridDecrypt = HybridDecryptFactory.getPrimitive(privateKeysetHandle); + + String contextInfo = "Tink"; + + byte[] ciphertext = hybridEncrypt.encrypt(PLAINTEXT.getBytes(), contextInfo.getBytes()); + + byte[] plaintextDecrypted = hybridDecrypt.decrypt(ciphertext, contextInfo.getBytes()); + + Assert.assertEquals(PLAINTEXT,new String(plaintextDecrypted)); + } +} + + diff --git a/libraries-server/README.md b/libraries-server/README.md index 28f963ade8..dc6bcd0716 100644 --- a/libraries-server/README.md +++ b/libraries-server/README.md @@ -3,7 +3,8 @@ - [Embedded Jetty Server in Java](http://www.baeldung.com/jetty-embedded) - [Introduction to Netty](http://www.baeldung.com/netty) - [Exceptions in Netty](http://www.baeldung.com/netty-exception-handling) -- [Programatically Create, Configure, and Run a Tomcat Server](http://www.baeldung.com/tomcat-programmatic-setup) +- [Programmatically Create, Configure and Run a Tomcat Server](http://www.baeldung.com/tomcat-programmatic-setup) - [Creating and Configuring Jetty 9 Server in Java](http://www.baeldung.com/jetty-java-programmatic) - [Testing Netty with EmbeddedChannel](http://www.baeldung.com/testing-netty-embedded-channel) - [MQTT Client in Java](https://www.baeldung.com/java-mqtt-client) +- [Guide to XMPP Smack Client](https://www.baeldung.com/xmpp-smack-chat-client) diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index 661f5f01d5..72794729a5 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -5,16 +5,17 @@ 0.0.1-SNAPSHOT libraries-server - + com.baeldung parent-modules 1.0.0-SNAPSHOT - + + org.eclipse.paho org.eclipse.paho.client.mqttv3 - 1.2.0 + ${eclipse.paho.client.mqttv3.version} @@ -64,13 +65,50 @@ ${junit.version} test - + org.apache.tomcat tomcat-catalina ${tomcat.version} + + + org.igniterealtime.smack + smack-tcp + ${smack.version} + + + + org.igniterealtime.smack + smack-im + ${smack.version} + + + + org.igniterealtime.smack + smack-extensions + ${smack.version} + + + + org.igniterealtime.smack + smack-java7 + ${smack.version} + + + + + org.nanohttpd + nanohttpd + ${nanohttpd.version} + + + org.nanohttpd + nanohttpd-nanolets + ${nanohttpd.version} + + @@ -80,8 +118,10 @@ 9.4.8.v20171121 4.1.20.Final 4.1 - 4.12 8.5.24 + 4.3.1 + 1.2.0 + 2.3.1 \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java b/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java new file mode 100644 index 0000000000..2fa54c3ae2 --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java @@ -0,0 +1,38 @@ +package com.baeldung.nanohttpd; + +import fi.iki.elonen.NanoHTTPD; +import fi.iki.elonen.router.RouterNanoHTTPD; + +import java.io.IOException; + +public class ApplicationController extends RouterNanoHTTPD { + + ApplicationController() throws IOException { + super(8072); + addMappings(); + start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); + } + + @Override + public void addMappings() { + addRoute("/", IndexHandler.class); + addRoute("/users", UserHandler.class); + } + + public static class UserHandler extends DefaultHandler { + @Override + public String getText() { + return "UserA, UserB, UserC"; + } + + @Override + public String getMimeType() { + return MIME_PLAINTEXT; + } + + @Override + public Response.IStatus getStatus() { + return Response.Status.OK; + } + } +} \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java b/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java new file mode 100644 index 0000000000..4a9c48fbfd --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java @@ -0,0 +1,22 @@ +package com.baeldung.nanohttpd; + +import fi.iki.elonen.NanoHTTPD; + +import java.io.IOException; + +public class ItemGetController extends NanoHTTPD { + + ItemGetController() throws IOException { + super(8071); + start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); + } + + @Override + public Response serve(IHTTPSession session) { + if (session.getMethod() == Method.GET) { + String itemIdRequestParam = session.getParameters().get("itemId").get(0); + return newFixedLengthResponse("Requested itemId = " + itemIdRequestParam); + } + return newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "The requested resource does not exist"); + } +} \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java new file mode 100644 index 0000000000..72db258164 --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java @@ -0,0 +1,40 @@ +package com.baeldung.smack; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.chat2.Chat; +import org.jivesoftware.smack.chat2.ChatManager; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jxmpp.jid.impl.JidCreate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StanzaThread implements Runnable { + + private Logger logger = LoggerFactory.getLogger(StanzaThread.class); + + @Override + public void run() { + XMPPTCPConnectionConfiguration config = null; + try { + config = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung2","baeldung2") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + AbstractXMPPConnection connection = new XMPPTCPConnection(config); + connection.connect(); + connection.login(); + + ChatManager chatManager = ChatManager.getInstanceFor(connection); + + Chat chat = chatManager.chatWith(JidCreate.from("baeldung@jabb3r.org").asEntityBareJidOrThrow()); + + chat.send("Hello!"); + + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } +} diff --git a/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java b/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java new file mode 100644 index 0000000000..003f6ee3b7 --- /dev/null +++ b/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.nanohttpd; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class ApplicationControllerUnitTest { + + private static final String BASE_URL = "http://localhost:8072/"; + private static final HttpClient CLIENT = HttpClientBuilder.create().build(); + + @BeforeClass + public static void setUp() throws IOException { + new ApplicationController(); + } + + @Test + public void givenServer_whenRootRouteRequested_thenHelloWorldReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(BASE_URL)); + assertTrue(IOUtils.toString(response.getEntity().getContent()).contains("Hello world!")); + assertEquals(200, response.getStatusLine().getStatusCode()); + } + + @Test + public void givenServer_whenUsersRequested_thenThenAllUsersReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(BASE_URL + "users")); + assertEquals("UserA, UserB, UserC", IOUtils.toString(response.getEntity().getContent())); + } +} \ No newline at end of file diff --git a/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java b/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java new file mode 100644 index 0000000000..3a4f0a4d98 --- /dev/null +++ b/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.nanohttpd; + +import static org.junit.Assert.*; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClientBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +public class ItemGetControllerUnitTest { + + private static final String URL = "http://localhost:8071"; + private static final HttpClient CLIENT = HttpClientBuilder.create().build(); + + @BeforeClass + public static void setUp() throws IOException { + new ItemGetController(); + } + + @Test + public void givenServer_whenDoingGet_thenParamIsReadCorrectly() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(URL + "?itemId=1234")); + assertEquals("Requested itemId = 1234", IOUtils.toString(response.getEntity().getContent())); + } + + @Test + public void givenServer_whenDoingPost_then404IsReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpPost(URL)); + assertEquals(404, response.getStatusLine().getStatusCode()); + } +} \ No newline at end of file diff --git a/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java new file mode 100644 index 0000000000..1e5e36ce24 --- /dev/null +++ b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.smack; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.chat2.ChatManager; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.jxmpp.stringprep.XmppStringprepException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +public class SmackIntegrationTest { + + private static AbstractXMPPConnection connection; + private Logger logger = LoggerFactory.getLogger(SmackIntegrationTest.class); + + @BeforeClass + public static void setup() throws IOException, InterruptedException, XMPPException, SmackException { + + XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung","baeldung") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + XMPPTCPConnectionConfiguration config2 = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung2","baeldung2") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + connection = new XMPPTCPConnection(config); + connection.connect(); + connection.login(); + + } + + @Test + public void whenSendMessageWithChat_thenReceiveMessage() throws XmppStringprepException, InterruptedException { + + CountDownLatch latch = new CountDownLatch(1); + ChatManager chatManager = ChatManager.getInstanceFor(connection); + final String[] expected = {null}; + + new StanzaThread().run(); + + chatManager.addIncomingListener((entityBareJid, message, chat) -> { + logger.info("Message arrived: " + message.getBody()); + expected[0] = message.getBody(); + latch.countDown(); + }); + + latch.await(); + Assert.assertEquals("Hello!", expected[0]); + } + + @Test + public void whenSendMessage_thenReceiveMessageWithFilter() throws XmppStringprepException, InterruptedException { + + CountDownLatch latch = new CountDownLatch(1); + final String[] expected = {null}; + + new StanzaThread().run(); + + connection.addAsyncStanzaListener(stanza -> { + if (stanza instanceof Message) { + Message message = (Message) stanza; + expected[0] = message.getBody(); + latch.countDown(); + } + }, StanzaTypeFilter.MESSAGE); + + latch.await(); + Assert.assertEquals("Hello!", expected[0]); + } +} diff --git a/libraries/README.md b/libraries/README.md index c1f16df6b4..f6f2cf4e07 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -6,7 +6,7 @@ - [Introduction to Apache Flink with Java](http://www.baeldung.com/apache-flink) - [Introduction to JSONassert](http://www.baeldung.com/jsonassert) - [Intro to JaVers](http://www.baeldung.com/javers) -- [Intro to Serenity BDD](http://www.baeldung.com/serenity-bdd) +- [Introduction to Serenity BDD](http://www.baeldung.com/serenity-bdd) - [Merging Streams in Java](http://www.baeldung.com/java-merge-streams) - [Serenity BDD and Screenplay](http://www.baeldung.com/serenity-screenplay) - [Introduction to Quartz](http://www.baeldung.com/quartz) @@ -14,15 +14,14 @@ - [Software Transactional Memory in Java Using Multiverse](http://www.baeldung.com/java-multiverse-stm) - [Serenity BDD with Spring and JBehave](http://www.baeldung.com/serenity-spring-jbehave) - [Locality-Sensitive Hashing in Java Using Java-LSH](http://www.baeldung.com/locality-sensitive-hashing) -- [Introduction to Awaitility](http://www.baeldung.com/awaitlity-testing) +- [Introduction to Awaitlity](http://www.baeldung.com/awaitlity-testing) - [Guide to the HyperLogLog Algorithm](http://www.baeldung.com/java-hyperloglog) - [Introduction to Neuroph](http://www.baeldung.com/neuroph) - [Quick Guide to RSS with Rome](http://www.baeldung.com/rome-rss) -- [Introduction to NoException](http://www.baeldung.com/introduction-to-noexception) - [Introduction to PCollections](http://www.baeldung.com/java-pcollections) - [Introduction to Hoverfly in Java](http://www.baeldung.com/hoverfly) - [Introduction to Eclipse Collections](http://www.baeldung.com/eclipse-collections) -- [DistinctBy in Java Stream API](http://www.baeldung.com/java-streams-distinct-by) +- [DistinctBy in the Java Stream API](http://www.baeldung.com/java-streams-distinct-by) - [Introduction to NoException](http://www.baeldung.com/no-exception) - [Introduction to Conflict-Free Replicated Data Types](http://www.baeldung.com/java-conflict-free-replicated-data-types) - [Introduction to javax.measure](http://www.baeldung.com/javax-measure) @@ -34,18 +33,14 @@ - [Introduction to Retrofit](http://www.baeldung.com/retrofit) - [Using Pairs in Java](http://www.baeldung.com/java-pairs) - [Introduction to Caffeine](http://www.baeldung.com/java-caching-caffeine) -- [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue) - [Introduction To Docx4J](http://www.baeldung.com/docx4j) - [Introduction to StreamEx](http://www.baeldung.com/streamex) - [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle) -- [Guide to google-http-client](http://www.baeldung.com/google-http-client) - [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client) - [A Docker Guide for Java](http://www.baeldung.com/docker-java-api) - [Introduction To OpenCSV](http://www.baeldung.com/opencsv) - [Introduction to Akka Actors in Java](http://www.baeldung.com/akka-actors-java) -- [Asynchronous HTTP with async-http-client in Java](http://www.baeldung.com/async-http-client) - [Introduction to Smooks](http://www.baeldung.com/smooks) -- [WebSockets with AsyncHttpClient](http://www.baeldung.com/async-http-client-websockets) - [A Guide to Infinispan in Java](http://www.baeldung.com/infinispan) - [Introduction to OpenCSV](http://www.baeldung.com/opencsv) - [A Guide to Unirest](http://www.baeldung.com/unirest) @@ -66,7 +61,9 @@ - [Exactly Once Processing in Kafka](https://www.baeldung.com/kafka-exactly-once) - [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) -- [Introduction to Functional Java](https://www.baeldung.com/java-functional-library +- [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. diff --git a/libraries/log4j.properties b/libraries/log4j.properties index 2173c5d96f..ed367509d1 100644 --- a/libraries/log4j.properties +++ b/libraries/log4j.properties @@ -1 +1,5 @@ log4j.rootLogger=INFO, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/libraries/pom.xml b/libraries/pom.xml index 2ad4871e3f..8e787bdc22 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -18,20 +18,12 @@ 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 @@ -130,10 +122,10 @@ ${serenity.version} test - - org.asciidoctor - asciidoctorj - + + org.asciidoctor + asciidoctorj + @@ -223,6 +215,12 @@ serenity-spring ${serenity.version} test + + + org.springframework + spring-test + + net.serenity-bdd @@ -318,6 +316,12 @@ pact-jvm-consumer-junit_2.11 ${pact.version} test + + + org.codehaus.groovy + groovy-all + + org.codehaus.groovy @@ -577,7 +581,7 @@ test test - + org.milyn milyn-smooks-all @@ -654,8 +658,8 @@ org.yaml snakeyaml - ${snakeyaml.version} - + ${snakeyaml.version} + com.numericalmethod @@ -675,14 +679,21 @@ ${mockftpserver.version} test + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.7.1 + + + + org.reflections + reflections + ${reflections.version} + + - false @@ -691,10 +702,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 @@ -738,7 +745,7 @@ JDO ${basedir}/datanucleus.properties ${basedir}/log4j.properties - true + false false @@ -822,15 +829,15 @@ 1.4.196 1.0 + 4.5.3 - 2.8.5 + 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 @@ -857,7 +864,6 @@ 2.0.0 1.7.0 3.0.14 - 2.2.0 9.1.5.Final 4.1 1.4.9 @@ -901,6 +907,8 @@ 1.1.0 2.7.1 3.6 + 0.9.11 + 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{ diff --git a/libraries/src/main/java/com/baeldung/ftp/FtpClient.java b/libraries/src/main/java/com/baeldung/ftp/FtpClient.java index 209bed35f0..f885ff13b3 100644 --- a/libraries/src/main/java/com/baeldung/ftp/FtpClient.java +++ b/libraries/src/main/java/com/baeldung/ftp/FtpClient.java @@ -59,5 +59,6 @@ class FtpClient { void downloadFile(String source, String destination) throws IOException { FileOutputStream out = new FileOutputStream(destination); ftp.retrieveFile(source, out); + out.close(); } } 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/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; 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()); + } +} diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java index fc7067520d..3201908bf7 100644 --- a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java +++ b/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java @@ -28,7 +28,7 @@ public class AdderMethodDirtiesContextIntegrationTest { @Test public void _1_givenNumber_whenAdd_thenSumWrong() { adderServiceSteps.whenAdd(); - adderServiceSteps.sumWrong(); + adderServiceSteps.summedUp(); } @Rule 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/linkrest/pom.xml b/linkrest/pom.xml index 073a173aff..b3d3bd374e 100644 --- a/linkrest/pom.xml +++ b/linkrest/pom.xml @@ -73,7 +73,6 @@ 2.9 4.0.B1 - 1.4.196 2.25.1 diff --git a/logging-modules/README.md b/logging-modules/README.md index 0f12d7eb22..17405847b1 100644 --- a/logging-modules/README.md +++ b/logging-modules/README.md @@ -4,5 +4,4 @@ ### Relevant Articles: - [Creating a Custom Logback Appender](http://www.baeldung.com/custom-logback-appender) -- [Get Log Output in JSON Format](http://www.baeldung.com/java-log-json-output) - [A Guide To Logback](http://www.baeldung.com/logback) diff --git a/logging-modules/log-mdc/pom.xml b/logging-modules/log-mdc/pom.xml index 8e9968085e..ae658e034e 100644 --- a/logging-modules/log-mdc/pom.xml +++ b/logging-modules/log-mdc/pom.xml @@ -29,13 +29,13 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided com.fasterxml.jackson.core jackson-databind - ${jackson.library} + ${jackson.version} @@ -98,12 +98,9 @@ - 1.2.17 2.7 3.3.6 3.3.0.Final - 3.1.0 - 2.8.5 2.4 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) diff --git a/logging-modules/log4j2/README.md b/logging-modules/log4j2/README.md index 2cf6f9768f..dd326bc7a1 100644 --- a/logging-modules/log4j2/README.md +++ b/logging-modules/log4j2/README.md @@ -4,3 +4,4 @@ - [Log4j 2 and Lambda Expressions](http://www.baeldung.com/log4j-2-lazy-logging) - [Programmatic Configuration with Log4j 2](http://www.baeldung.com/log4j2-programmatic-config) - [Creating a Custom Log4j2 Appender](https://www.baeldung.com/log4j2-custom-appender) +- [Get Log Output in JSON](http://www.baeldung.com/java-log-json-output) diff --git a/logging-modules/log4j2/pom.xml b/logging-modules/log4j2/pom.xml index d46f92dcd6..db0c6eb659 100644 --- a/logging-modules/log4j2/pom.xml +++ b/logging-modules/log4j2/pom.xml @@ -78,7 +78,7 @@ - integration + integration-lite-first @@ -115,8 +115,6 @@ - 2.9.5 - 1.4.193 2.1.1 2.11.0 yyyyMMddHHmmss diff --git a/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java b/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java index 020aaafc74..e340ebb784 100644 --- a/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java +++ b/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java @@ -23,7 +23,7 @@ public class MapAppenderIntegrationTest { @Test public void whenLoggerEmitsLoggingEvent_thenAppenderReceivesEvent() throws Exception { - logger.info("Test from {}", this.getClass() + logger.error("Error log message from {}", this.getClass() .getSimpleName()); LoggerContext context = LoggerContext.getContext(false); Configuration config = context.getConfiguration(); diff --git a/logging-modules/logback/README.md b/logging-modules/logback/README.md index e69de29bb2..58dc8ce541 100644 --- a/logging-modules/logback/README.md +++ b/logging-modules/logback/README.md @@ -0,0 +1,4 @@ +### Relevant Articles: + +- [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output) +- [SLF4J Warning: Class Path Contains Multiple SLF4J Bindings](https://www.baeldung.com/slf4j-classpath-multiple-bindings) diff --git a/logging-modules/logback/pom.xml b/logging-modules/logback/pom.xml index e917754b3c..22a89124b5 100644 --- a/logging-modules/logback/pom.xml +++ b/logging-modules/logback/pom.xml @@ -4,9 +4,9 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - logback logback 0.1-SNAPSHOT + logback com.baeldung @@ -37,12 +37,28 @@ jackson-databind ${jackson.version} + + org.docx4j + docx4j + ${docx4j.version} + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + 1.2.3 0.1.5 - 2.9.3 + 3.3.5 diff --git a/logging-modules/pom.xml b/logging-modules/pom.xml new file mode 100644 index 0000000000..a303e50ff1 --- /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/lombok-custom/README.md b/lombok-custom/README.md new file mode 100644 index 0000000000..bfc784ea7e --- /dev/null +++ b/lombok-custom/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Implementing a Custom Lombok Annotation](https://www.baeldung.com/lombok-custom-annotation) diff --git a/lombok-custom/pom.xml b/lombok-custom/pom.xml index 41bd042a5e..cfbe629945 100644 --- a/lombok-custom/pom.xml +++ b/lombok-custom/pom.xml @@ -2,34 +2,36 @@ + + 4.0.0 + lombok-custom + lombok-custom + 0.1-SNAPSHOT + parent-modules com.baeldung 1.0.0-SNAPSHOT - - 4.0.0 - lombok-custom - 0.1-SNAPSHOT - + org.projectlombok lombok - 1.14.8 + ${lombok.version} provided org.kohsuke.metainf-services metainf-services - 1.8 + ${metainf-services.version} org.eclipse.jdt core - 3.3.0-v_771 + ${eclipse.jdt.core.version} @@ -54,5 +56,12 @@ + + + 1.14.8 + 1.8 + 3.3.0-v_771 + - \ No newline at end of file + + diff --git a/lombok/README.md b/lombok/README.md index bd6282fd18..4ff7ca7921 100644 --- a/lombok/README.md +++ b/lombok/README.md @@ -5,3 +5,6 @@ - [Lombok @Builder with Inheritance](https://www.baeldung.com/lombok-builder-inheritance) - [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) + diff --git a/lombok/pom.xml b/lombok/pom.xml index 7ad2e3dc83..2acf9e240d 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -76,11 +76,11 @@ - 1.16.18 + 1.18.4 1.0.0.Final - 1.16.10.0 + 1.18.4.0 3.8.0 diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java similarity index 86% rename from lombok/src/main/java/com/baeldung/lombok/builder/Child.java rename to lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java index 70f6d9c46e..4cfcc22fb2 100644 --- a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java @@ -1,4 +1,4 @@ -package com.baeldung.lombok.builder; +package com.baeldung.lombok.builder.inheritance.buildermethodname; import lombok.Builder; import lombok.Getter; diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java similarity index 70% rename from lombok/src/main/java/com/baeldung/lombok/builder/Parent.java rename to lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java index 0cf76d4b00..93e48ee44e 100644 --- a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java @@ -1,4 +1,4 @@ -package com.baeldung.lombok.builder; +package com.baeldung.lombok.builder.inheritance.buildermethodname; import lombok.Builder; import lombok.Getter; diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java new file mode 100644 index 0000000000..c8eea84b97 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.builder.inheritance.buildermethodname; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class Student extends Child { + + private final String schoolName; + + @Builder(builderMethodName = "studentBuilder") + public Student(String parentName, int parentAge, String childName, int childAge, String schoolName) { + super(parentName, parentAge, childName, childAge); + this.schoolName = schoolName; + } +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java new file mode 100644 index 0000000000..92285ebdc3 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java @@ -0,0 +1,11 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Child extends Parent { + private final String childName; + private final int childAge; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java new file mode 100644 index 0000000000..b8e0934520 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java @@ -0,0 +1,11 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Parent { + private final String parentName; + private final int parentAge; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java new file mode 100644 index 0000000000..db43bacafa --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java @@ -0,0 +1,10 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Student extends Child { + private final String schoolName; +} 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/main/java/com/baeldung/lombok/getter/GetterLazy.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterLazy.java new file mode 100644 index 0000000000..5ac82a74d8 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterLazy.java @@ -0,0 +1,36 @@ +package com.baeldung.lombok.getter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import lombok.Getter; + +public class GetterLazy { + + private static final String DELIMETER = ","; + + @Getter(lazy = true) + private final Map transactions = readTxnsFromFile(); + + private Map readTxnsFromFile() { + + final Map cache = new HashMap<>(); + List txnRows = readTxnListFromFile(); + + txnRows.forEach(s -> { + String[] txnIdValueTuple = s.split(DELIMETER); + cache.put(txnIdValueTuple[0], Long.parseLong(txnIdValueTuple[1])); + }); + + return cache; + } + + private List readTxnListFromFile() { + + // read large file + return Stream.of("file content here").collect(Collectors.toList()); + } +} diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java index 56a380569d..546c38f140 100644 --- a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java +++ b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java @@ -40,20 +40,4 @@ public class BuilderUnitTest { assertThat(testImmutableClient.getName()).isEqualTo("foo"); assertThat(testImmutableClient.getId()).isEqualTo(1); } - - @Test - public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() { - Child child = Child.childBuilder() - .parentName("Andrea") - .parentAge(38) - .childName("Emma") - .childAge(6) - .build(); - - assertThat(child.getChildName()).isEqualTo("Emma"); - assertThat(child.getChildAge()).isEqualTo(6); - assertThat(child.getParentName()).isEqualTo("Andrea"); - assertThat(child.getParentAge()).isEqualTo(38); - } - } diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java new file mode 100644 index 0000000000..cf50b2577b --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.lombok.builder.inheritance.buildermethodname; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class BuilderInheritanceUsingMethodNameUnitTest { + + @Test + public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() { + Child child = Child.childBuilder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + assertThat(child.getChildName()).isEqualTo("Emma"); + assertThat(child.getChildAge()).isEqualTo(6); + assertThat(child.getParentName()).isEqualTo("Andrea"); + assertThat(child.getParentAge()).isEqualTo(38); + } + + @Test + public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() { + Student student = Student.studentBuilder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("Baeldung High School") + .build(); + + assertThat(student.getChildName()).isEqualTo("Emma"); + assertThat(student.getChildAge()).isEqualTo(6); + assertThat(student.getParentName()).isEqualTo("Andrea"); + assertThat(student.getParentAge()).isEqualTo(38); + assertThat(student.getSchoolName()).isEqualTo("Baeldung High School"); + } +} diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java new file mode 100644 index 0000000000..72bfa6567b --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java @@ -0,0 +1,96 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class BuilderInheritanceUsingSuperBuilderUnitTest { + + @Test + public void givenSuperBuilderOnParentAndOnChild_ChildInheritingParentIsBuilt() { + Child child = Child.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + assertThat(child.getChildName()).isEqualTo("Emma"); + assertThat(child.getChildAge()).isEqualTo(6); + assertThat(child.getParentName()).isEqualTo("Andrea"); + assertThat(child.getParentAge()).isEqualTo(38); + } + + @Test + public void givenSuperBuilderOnParent_StandardBuilderIsBuilt() { + Parent parent = Parent.builder() + .parentName("Andrea") + .parentAge(38) + .build(); + + assertThat(parent.getParentName()).isEqualTo("Andrea"); + assertThat(parent.getParentAge()).isEqualTo(38); + } + + @Test + public void givenToBuilderIsSetToTrueOnParentAndChild_DeepCopyViaBuilderIsPossible() { + Child child1 = Child.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + Child child2 = child1.toBuilder() + .childName("Anna") + .build(); + + assertThat(child2.getChildName()).isEqualTo("Anna"); + assertThat(child2.getChildAge()).isEqualTo(6); + assertThat(child2.getParentName()).isEqualTo("Andrea"); + assertThat(child2.getParentAge()).isEqualTo(38); + + } + + @Test + public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() { + Student student = Student.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("Baeldung High School") + .build(); + + assertThat(student.getChildName()).isEqualTo("Emma"); + assertThat(student.getChildAge()).isEqualTo(6); + assertThat(student.getParentName()).isEqualTo("Andrea"); + assertThat(student.getParentAge()).isEqualTo(38); + assertThat(student.getSchoolName()).isEqualTo("Baeldung High School"); + } + + @Test + public void givenToBuilderIsSetToTrueOnParentChildAndStudent_DeepCopyViaBuilderIsPossible() { + Student student1 = Student.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("School 1") + .build(); + + Student student2 = student1.toBuilder() + .childName("Anna") + .schoolName("School 2") + .build(); + + assertThat(student2.getChildName()).isEqualTo("Anna"); + assertThat(student2.getChildAge()).isEqualTo(6); + assertThat(student2.getParentName()).isEqualTo("Andrea"); + assertThat(student2.getParentAge()).isEqualTo(38); + assertThat(student2.getSchoolName()).isEqualTo("School 2"); + + } + + +} 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")); + } + +} diff --git a/lucene/pom.xml b/lucene/pom.xml index f427cfd8a7..3d1ce61782 100644 --- a/lucene/pom.xml +++ b/lucene/pom.xml @@ -32,8 +32,6 @@ - - 1.16.18 1.0.0.Final diff --git a/mapstruct/pom.xml b/mapstruct/pom.xml index 6c274dfcf2..0493775f85 100644 --- a/mapstruct/pom.xml +++ b/mapstruct/pom.xml @@ -30,6 +30,11 @@ ${springframework.version} test + + org.projectlombok + lombok + ${org.projectlombok.version} + @@ -48,6 +53,11 @@ mapstruct-processor ${org.mapstruct.version} + + org.projectlombok + lombok + ${org.projectlombok.version} + @@ -55,10 +65,11 @@ - 1.1.0.Final + 1.3.0.Beta2 4.3.4.RELEASE 1.8 1.8 + 1.18.4 diff --git a/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java b/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java new file mode 100644 index 0000000000..51aa8ccac2 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/CarDTO.java @@ -0,0 +1,11 @@ +package com.baeldung.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CarDTO { + private int id; + private String name; +} diff --git a/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java b/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java new file mode 100644 index 0000000000..ace7a2bc7d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/PersonDTO.java @@ -0,0 +1,33 @@ +package com.baeldung.dto; + +public class PersonDTO { + + private String id; + private String name; + + public PersonDTO() { + + } + + public PersonDTO(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/mapstruct/src/main/java/com/baeldung/entity/Car.java b/mapstruct/src/main/java/com/baeldung/entity/Car.java new file mode 100644 index 0000000000..8559b4a77d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Car.java @@ -0,0 +1,11 @@ +package com.baeldung.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Car { + private int id; + private String name; +} diff --git a/mapstruct/src/main/java/com/baeldung/entity/Person.java b/mapstruct/src/main/java/com/baeldung/entity/Person.java new file mode 100644 index 0000000000..5f73ee1130 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Person.java @@ -0,0 +1,33 @@ +package com.baeldung.entity; + +public class Person { + + private String id; + private String name; + + public Person() { + + } + + public Person(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java new file mode 100644 index 0000000000..c18fa44f8d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/CarMapper.java @@ -0,0 +1,15 @@ +package com.baeldung.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import com.baeldung.dto.CarDTO; +import com.baeldung.entity.Car; + +@Mapper +public interface CarMapper { + + CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); + + CarDTO carToCarDTO(Car car); +} diff --git a/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java new file mode 100644 index 0000000000..9b9e132b5d --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/PersonMapper.java @@ -0,0 +1,17 @@ +package com.baeldung.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import com.baeldung.dto.PersonDTO; +import com.baeldung.entity.Person; + +@Mapper +public interface PersonMapper { + + PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class); + + @Mapping(target = "id", source = "person.id", defaultExpression = "java(java.util.UUID.randomUUID().toString())") + PersonDTO personToPersonDTO(Person person); +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java new file mode 100644 index 0000000000..32cae56c2e --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/CarMapperUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.mapper; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.dto.CarDTO; +import com.baeldung.entity.Car; + +public class CarMapperUnitTest { + + @Test + public void givenCarEntitytoCar_whenMaps_thenCorrect() { + + Car entity = new Car(); + entity.setId(1); + entity.setName("Toyota"); + + CarDTO carDto = CarMapper.INSTANCE.carToCarDTO(entity); + + assertEquals(carDto.getId(), entity.getId()); + assertEquals(carDto.getName(), entity.getName()); + } +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java b/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java new file mode 100644 index 0000000000..fe4c52ac89 --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/PersonMapperUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.mapper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import com.baeldung.dto.PersonDTO; +import com.baeldung.entity.Person; + +public class PersonMapperUnitTest { + + @Test + public void givenPersonEntitytoPersonWithExpression_whenMaps_thenCorrect() { + + Person entity = new Person(); + entity.setName("Micheal"); + + PersonDTO personDto = PersonMapper.INSTANCE.personToPersonDTO(entity); + + assertNull(entity.getId()); + assertNotNull(personDto.getId()); + assertEquals(personDto.getName(), entity.getName()); + } +} \ No newline at end of file diff --git a/maven-archetype/src/main/resources/archetype-resources/pom.xml b/maven-archetype/src/main/resources/archetype-resources/pom.xml index eb69f64626..a5c813652d 100644 --- a/maven-archetype/src/main/resources/archetype-resources/pom.xml +++ b/maven-archetype/src/main/resources/archetype-resources/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - ${groupId} ${artifactId} ${version} diff --git a/maven-java-11/multimodule-maven-project/daomodule/pom.xml b/maven-java-11/multimodule-maven-project/daomodule/pom.xml new file mode 100644 index 0000000000..5520c5a90a --- /dev/null +++ b/maven-java-11/multimodule-maven-project/daomodule/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + com.baeldung.daomodule + daomodule + jar + 1.0 + daomodule + + + com.baeldung.multimodule-maven-project + multimodule-maven-project + 1.0 + + diff --git a/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java new file mode 100644 index 0000000000..f86ae8abb3 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java @@ -0,0 +1,12 @@ +package com.baeldung.dao; + +import java.util.List; +import java.util.Optional; + +public interface Dao { + + Optional findById(int id); + + List findAll(); + +} diff --git a/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java new file mode 100644 index 0000000000..072d7ad007 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.dao { + exports com.baeldung.dao; +} diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml b/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml new file mode 100644 index 0000000000..747722e912 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + com.baeldung.entitymodule + entitymodule + jar + 1.0 + entitymodule + + + com.baeldung.multimodule-maven-project + multimodule-maven-project + 1.0 + + + + 11 + 11 + + diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java new file mode 100644 index 0000000000..22022a2e6d --- /dev/null +++ b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java @@ -0,0 +1,19 @@ +package com.baeldung.entity; + +public class User { + + private final String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "User{" + "name=" + name + '}'; + } +} diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java new file mode 100644 index 0000000000..67a3097352 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.entity { + exports com.baeldung.entity; +} diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml b/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml new file mode 100644 index 0000000000..3e5ec122ff --- /dev/null +++ b/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + com.baeldung.mainappmodule + mainappmodule + 1.0 + jar + mainappmodule + + + com.baeldung.multimodule-maven-project + multimodule-maven-project + 1.0 + + + + + com.baeldung.entitymodule + entitymodule + 1.0 + + + com.baeldung.daomodule + daomodule + 1.0 + + + com.baeldung.userdaomodule + userdaomodule + 1.0 + + + diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java new file mode 100644 index 0000000000..0c0df7461b --- /dev/null +++ b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java @@ -0,0 +1,19 @@ +package com.baeldung.mainapp; + +import com.baeldung.dao.Dao; +import com.baeldung.entity.User; +import com.baeldung.userdao.UserDao; +import java.util.HashMap; +import java.util.Map; + +public class Application { + + public static void main(String[] args) { + Map users = new HashMap<>(); + users.put(1, new User("Julie")); + users.put(2, new User("David")); + Dao userDao = new UserDao(users); + userDao.findAll().forEach(System.out::println); + } + +} diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java new file mode 100644 index 0000000000..c688fcf7de --- /dev/null +++ b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.mainapp { + requires com.baeldung.entity; + requires com.baeldung.userdao; + requires com.baeldung.dao; + uses com.baeldung.dao.Dao; +} diff --git a/maven-java-11/multimodule-maven-project/pom.xml b/maven-java-11/multimodule-maven-project/pom.xml new file mode 100644 index 0000000000..7e2eb0dd7b --- /dev/null +++ b/maven-java-11/multimodule-maven-project/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + com.baeldung.multimodule-maven-project + multimodule-maven-project + 1.0 + pom + multimodule-maven-project + + + com.baeldung.maven-java-11 + maven-java-11 + 1.0 + + + + entitymodule + daomodule + userdaomodule + mainappmodule + + + + + + junit + junit + 4.12 + test + + + org.assertj + assertj-core + 3.12.2 + test + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + + + + + UTF-8 + + diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml b/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml new file mode 100644 index 0000000000..68e7ae9b82 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + com.baeldung.userdaomodule + userdaomodule + 1.0 + jar + userdaomodule + + + com.baeldung.multimodule-maven-project + multimodule-maven-project + 1.0 + + + + + com.baeldung.entitymodule + entitymodule + 1.0 + + + com.baeldung.daomodule + daomodule + 1.0 + + + junit + junit + test + + + diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java new file mode 100644 index 0000000000..1f1ea38a60 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java @@ -0,0 +1,32 @@ +package com.baeldung.userdao; + +import com.baeldung.dao.Dao; +import com.baeldung.entity.User; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class UserDao implements Dao { + + private final Map users; + + public UserDao() { + users = new HashMap<>(); + } + + public UserDao(Map users) { + this.users = users; + } + + @Override + public List findAll() { + return new ArrayList<>(users.values()); + } + + @Override + public Optional findById(int id) { + return Optional.ofNullable(users.get(id)); + } +} \ No newline at end of file diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java new file mode 100644 index 0000000000..f1cb217e23 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.userdao { + requires com.baeldung.entity; + requires com.baeldung.dao; + provides com.baeldung.dao.Dao with com.baeldung.userdao.UserDao; + exports com.baeldung.userdao; +} diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java new file mode 100644 index 0000000000..191d17ff32 --- /dev/null +++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.userdao.test; + +import com.baeldung.dao.Dao; +import com.baeldung.entity.User; +import com.baeldung.userdao.UserDao; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; +import org.junit.Before; +import org.junit.Test; + +public class UserDaoUnitTest { + + private Dao userDao; + + @Before + public void setUpUserDaoInstance() { + Map users = new HashMap<>(); + users.put(1, new User("Julie")); + users.put(2, new User("David")); + userDao = new UserDao(users); + } + + @Test + public void givenUserDaoIntance_whenCalledFindById_thenCorrect() { + assertThat(userDao.findById(1), isA(Optional.class)); + } + + @Test + public void givenUserDaoIntance_whenCalledFindAll_thenCorrect() { + assertThat(userDao.findAll(), isA(List.class)); + } +} diff --git a/maven-java-11/pom.xml b/maven-java-11/pom.xml new file mode 100644 index 0000000000..5ae4c00892 --- /dev/null +++ b/maven-java-11/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + com.baeldung.maven-java-11 + maven-java-11 + 1.0 + pom + maven-java-11 + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + multimodule-maven-project + + + + UTF-8 + 11 + 11 + + diff --git a/maven-polyglot/maven-polyglot-json-extension/pom.xml b/maven-polyglot/maven-polyglot-json-extension/pom.xml index fe1e025d1f..5b18529ec5 100644 --- a/maven-polyglot/maven-polyglot-json-extension/pom.xml +++ b/maven-polyglot/maven-polyglot-json-extension/pom.xml @@ -7,11 +7,6 @@ maven-polyglot-json-extension 1.0-SNAPSHOT maven-polyglot-json-extension - - - 1.8 - 1.8 - @@ -43,5 +38,10 @@ + + + 1.8 + 1.8 + \ No newline at end of file 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/README.md b/maven/README.md index 1c0e50f95a..6d1a7081b7 100644 --- a/maven/README.md +++ b/maven/README.md @@ -14,3 +14,6 @@ - [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) +- [Eclipse Error: web.xml is missing and failOnMissingWebXml is set to true](https://www.baeldung.com/eclipse-error-web-xml-missing) +- [Guide to Maven Profiles](https://www.baeldung.com/maven-profiles) 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 diff --git a/maven/custom-rule/pom.xml b/maven/custom-rule/pom.xml new file mode 100644 index 0000000000..2fbeb18922 --- /dev/null +++ b/maven/custom-rule/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + custom-rule + custom-rule + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + + + + + 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 + ${plexus-container-default.version} + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + 3.0.0-M2 + 2.0.9 + 1.0-alpha-9 + + 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..b18be4f43d --- /dev/null +++ b/maven/maven-enforcer/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + maven-enforcer + maven-enforcer + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + + + + + 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/maven-war-plugin/pom.xml b/maven/maven-war-plugin/pom.xml new file mode 100644 index 0000000000..517c08978f --- /dev/null +++ b/maven/maven-war-plugin/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + com.baeldung + maven-war-plugin-property + 0.0.1-SNAPSHOT + war + maven-war-plugin-property + + + + + maven-war-plugin + + 3.1.0 + + + false + + + + + + + + false + + \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index 01fd28db74..ecb031fc11 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -4,8 +4,13 @@ com.baeldung maven 0.0.1-SNAPSHOT - maven - war + maven + pom + + + custom-rule + maven-enforcer + diff --git a/maven/profiles/pom.xml b/maven/profiles/pom.xml new file mode 100644 index 0000000000..110016f3a2 --- /dev/null +++ b/maven/profiles/pom.xml @@ -0,0 +1,88 @@ + + 4.0.0 + com.baeldung + profiles + 0.0.1-SNAPSHOT + profiles + + + + no-tests + + true + + + + integration-tests + + true + + + + mutation-tests + + + active-on-jdk-11 + + 11 + + + + active-on-windows-10 + + + windows 10 + Windows + amd64 + 10.0 + + + + + active-on-property-environment + + + environment + !test + + + + + active-on-missing-file + + + target/testreport.html + + + + + active-on-present-file + + + target/artifact.jar + + + + + + + + + org.apache.maven.plugins + maven-help-plugin + 3.2.0 + + + show-profiles + compile + + active-profiles + + + + + + + \ No newline at end of file diff --git a/maven/versions-maven-plugin/original/pom.xml b/maven/versions-maven-plugin/original/pom.xml index 295c77b860..df8ee9a20e 100644 --- a/maven/versions-maven-plugin/original/pom.xml +++ b/maven/versions-maven-plugin/original/pom.xml @@ -6,28 +6,24 @@ versions-maven-plugin-example 0.0.1-SNAPSHOT - - 1.15 - - commons-io commons-io - 2.3 + ${commons-io.version} org.apache.commons commons-collections4 - 4.0 + ${commons-collections4.version} org.apache.commons commons-lang3 - 3.0 + ${commons-lang3.version} @@ -39,7 +35,7 @@ commons-beanutils commons-beanutils - 1.9.1-SNAPSHOT + ${commons-beanutils.version} @@ -73,4 +69,12 @@ + + 1.15 + 2.3 + 4.0 + 3.0 + 1.9.1 + + \ No newline at end of file diff --git a/maven/versions-maven-plugin/pom.xml b/maven/versions-maven-plugin/pom.xml index dc0cba75f9..e0714bf0e0 100644 --- a/maven/versions-maven-plugin/pom.xml +++ b/maven/versions-maven-plugin/pom.xml @@ -6,10 +6,6 @@ versions-maven-plugin 0.0.1-SNAPSHOT versions-maven-plugin - - - 1.15 - @@ -73,5 +69,9 @@ + + + 1.15 + \ No newline at end of file diff --git a/metrics/pom.xml b/metrics/pom.xml index 79d340aa49..014931a957 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 metrics - metrics - + metrics + parent-modules com.baeldung @@ -66,7 +66,7 @@ org.springframework.boot spring-boot-starter-web - ${spring.boot.ver} + ${spring-boot-starter-web.version} @@ -85,46 +85,25 @@ spectator-api ${spectator-api.version} - - - org.assertj - assertj-core - test - - + + + org.assertj + assertj-core + ${assertj-core.version} + test + + - - - - org.springframework.boot - spring-boot-dependencies - pom - import - ${spring.boot.ver} - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone - - false - - - - 3.1.2 3.1.0 0.12.17 0.12.0.RELEASE - 2.0.0.M5 2.9.1 0.57.1 + 2.0.7.RELEASE + 3.11.1 diff --git a/metrics/src/main/java/com/baeldung/metrics/micrometer/MicrometerApp.java b/metrics/src/main/java/com/baeldung/metrics/micrometer/MicrometerApp.java index cf818f6600..1d738085ce 100644 --- a/metrics/src/main/java/com/baeldung/metrics/micrometer/MicrometerApp.java +++ b/metrics/src/main/java/com/baeldung/metrics/micrometer/MicrometerApp.java @@ -1,10 +1,11 @@ package com.baeldung.metrics.micrometer; -import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import io.micrometer.core.instrument.binder.JvmThreadMetrics; + @SpringBootApplication public class MicrometerApp { diff --git a/micronaut/pom.xml b/micronaut/pom.xml index aa69c77f73..2a8d135483 100644 --- a/micronaut/pom.xml +++ b/micronaut/pom.xml @@ -4,12 +4,6 @@ micronaut 0.1 micronaut - - - com.baeldung.micronaut.helloworld.server.ServerApplication - 1.0.0.RC2 - 1.8 - @@ -133,4 +127,10 @@ + + + com.baeldung.micronaut.helloworld.server.ServerApplication + 1.0.0.RC2 + 1.8 + diff --git a/msf4j/pom.xml b/msf4j/pom.xml index 4a6f63159d..2a862ac289 100644 --- a/msf4j/pom.xml +++ b/msf4j/pom.xml @@ -23,6 +23,7 @@ + org.wso2.msf4j diff --git a/mustache/pom.xml b/mustache/pom.xml index a276dfbf43..027d62ebc4 100644 --- a/mustache/pom.xml +++ b/mustache/pom.xml @@ -3,14 +3,14 @@ 4.0.0 mustache - jar mustache + jar - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -30,6 +30,11 @@ log4j ${log4j.version} + + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot diff --git a/mustache/src/main/resources/application.properties b/mustache/src/main/resources/application.properties index e69de29bb2..011bbae980 100644 --- a/mustache/src/main/resources/application.properties +++ b/mustache/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.mustache.suffix:.html \ No newline at end of file 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) 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/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/optaplanner/pom.xml b/optaplanner/pom.xml index fbce0ea072..93b1e68264 100644 --- a/optaplanner/pom.xml +++ b/optaplanner/pom.xml @@ -18,11 +18,6 @@ optaplanner-core 7.9.0.Final - - - - - \ No newline at end of file diff --git a/osgi/osgi-intro-sample-activator/pom.xml b/osgi/osgi-intro-sample-activator/pom.xml index 77d7198698..2bc1c20eed 100644 --- a/osgi/osgi-intro-sample-activator/pom.xml +++ b/osgi/osgi-intro-sample-activator/pom.xml @@ -2,9 +2,10 @@ 4.0.0 + osgi-intro-sample-activator + osgi-intro-sample-activator bundle - osgi-intro-sample-activator 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/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 280d226e95..f0e921bf37 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -1,9 +1,9 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 parent-boot-2 0.0.1-SNAPSHOT - parent-boot-2 + parent-boot-2 pom Parent for all Spring Boot 2 modules @@ -13,7 +13,7 @@ 1.0.0-SNAPSHOT - + org.springframework.boot @@ -28,7 +28,7 @@ io.rest-assured rest-assured - + org.springframework.boot spring-boot-starter-test @@ -36,22 +36,22 @@ - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - ${start-class} - - - - - - - + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + ${start-class} + + + + + + + thin-jar @@ -75,11 +75,9 @@ - 3.1.0 + 3.3.0 - 1.0.11.RELEASE - 2.1.1.RELEASE + 1.0.22.RELEASE + 2.1.6.RELEASE - - diff --git a/parent-boot-performance/README.md b/parent-boot-performance/README.md new file mode 100644 index 0000000000..fce9e101da --- /dev/null +++ b/parent-boot-performance/README.md @@ -0,0 +1 @@ +This is a parent module for projects that want to take advantage of the latest Spring Boot improvements/features. \ No newline at end of file diff --git a/parent-boot-performance/pom.xml b/parent-boot-performance/pom.xml new file mode 100644 index 0000000000..b7d12e2ba4 --- /dev/null +++ b/parent-boot-performance/pom.xml @@ -0,0 +1,92 @@ + + 4.0.0 + parent-boot-performance + 0.0.1-SNAPSHOT + parent-boot-performance + pom + Parent for all modules that want to take advantage of the latest Spring Boot improvements/features. Current version: 2.2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + io.rest-assured + rest-assured + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + ${start-class} + + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + + thin-jar + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.springframework.boot.experimental + spring-boot-thin-layout + ${thin.version} + + + + + + + + + + 3.1.0 + + 1.0.21.RELEASE + 2.2.0.M3 + + diff --git a/parent-java/pom.xml b/parent-java/pom.xml index 86be34d508..cb3e205871 100644 --- a/parent-java/pom.xml +++ b/parent-java/pom.xml @@ -4,9 +4,9 @@ com.baeldung parent-java 0.0.1-SNAPSHOT - pom parent-java Parent for all java modules + pom com.baeldung @@ -24,7 +24,7 @@ - 22.0 + 23.0 - \ No newline at end of file + diff --git a/parent-kotlin/pom.xml b/parent-kotlin/pom.xml index f8283bd920..6f7fe6c102 100644 --- a/parent-kotlin/pom.xml +++ b/parent-kotlin/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 parent-kotlin - pom parent-kotlin + pom Parent for all kotlin modules @@ -108,6 +108,9 @@ ${project.basedir}/src/main/java ${java.version} + + -Xjvm-default=enable + @@ -202,10 +205,10 @@ - 1.3.0 + 1.3.30 1.0.0 0.9.5 - 3.11.0 - 1.2.0 + 3.12.0 + 1.3.2 diff --git a/parent-spring-4/pom.xml b/parent-spring-4/pom.xml index 9b3c42599b..d7eea44989 100644 --- a/parent-spring-4/pom.xml +++ b/parent-spring-4/pom.xml @@ -4,8 +4,8 @@ com.baeldung parent-spring-4 0.0.1-SNAPSHOT - pom parent-spring-4 + pom Parent for all spring 4 core modules @@ -29,7 +29,7 @@ - 4.3.20.RELEASE + 4.3.22.RELEASE 5.0.2 diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 6a15f38884..84df8cf30a 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -4,9 +4,9 @@ com.baeldung parent-spring-5 0.0.1-SNAPSHOT - pom parent-spring-5 Parent for all spring 5 core modules + pom com.baeldung @@ -29,11 +29,9 @@ - 5.0.6.RELEASE + 5.1.4.RELEASE 5.0.2 - 2.9.6 - 2.9.6 - 5.0.6.RELEASE + 5.1.4.RELEASE \ No newline at end of file diff --git a/patterns/README.md b/patterns/README.md deleted file mode 100644 index 221cba6456..0000000000 --- a/patterns/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### 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) -- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern) -- [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) -- [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern) - diff --git a/patterns/design-patterns-2/README.md b/patterns/design-patterns-2/README.md new file mode 100644 index 0000000000..8e4ef657e1 --- /dev/null +++ b/patterns/design-patterns-2/README.md @@ -0,0 +1,5 @@ +### Relevant Articles + +- [The Mediator Pattern in Java](https://www.baeldung.com/java-mediator-pattern) +- [Introduction to the Null Object Pattern](https://www.baeldung.com/java-null-object-pattern) +- [Avoid Check for Null Statement in Java](https://www.baeldung.com/java-avoid-null-check) diff --git a/patterns/design-patterns-2/pom.xml b/patterns/design-patterns-2/pom.xml new file mode 100644 index 0000000000..5c3e70b046 --- /dev/null +++ b/patterns/design-patterns-2/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + design-patterns-2 + 1.0 + design-patterns-2 + jar + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + + + 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/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/main/java/com/baeldung/nullobject/JmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java new file mode 100644 index 0000000000..7d8215fead --- /dev/null +++ b/patterns/design-patterns-2/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-2/src/main/java/com/baeldung/nullobject/Message.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java new file mode 100644 index 0000000000..9086b6d92d --- /dev/null +++ b/patterns/design-patterns-2/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-2/src/main/java/com/baeldung/nullobject/NullRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java new file mode 100644 index 0000000000..a0065a321d --- /dev/null +++ b/patterns/design-patterns-2/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) { + // do nothing + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java new file mode 100644 index 0000000000..3e67de9558 --- /dev/null +++ b/patterns/design-patterns-2/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-2/src/main/java/com/baeldung/nullobject/RouterFactory.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java new file mode 100644 index 0000000000..ba80834865 --- /dev/null +++ b/patterns/design-patterns-2/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-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java new file mode 100644 index 0000000000..282b066085 --- /dev/null +++ b/patterns/design-patterns-2/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-2/src/main/java/com/baeldung/nullobject/SmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java new file mode 100644 index 0000000000..3e8e2f15f3 --- /dev/null +++ b/patterns/design-patterns-2/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 gateway. Msg: " + msg); + } + +} 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..d5dd56e760 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingOptional.java @@ -0,0 +1,23 @@ +package com.baeldung.nulls; + +import java.util.Optional; + +public class UsingOptional { + + public Optional process(boolean processed) { + + String response = doSomething(processed); + + return Optional.ofNullable(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/mediator/MediatorIntegrationTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/MediatorIntegrationTest.java new file mode 100644 index 0000000000..0bda659f3f --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/MediatorIntegrationTest.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 MediatorIntegrationTest { + + 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 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 diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md index e56872b3fd..605fdc0d6e 100644 --- a/patterns/design-patterns/README.md +++ b/patterns/design-patterns/README.md @@ -14,3 +14,9 @@ - [State Design Pattern in Java](https://www.baeldung.com/java-state-design-pattern) - [The Decorator Pattern in Java](https://www.baeldung.com/java-decorator-pattern) - [Abstract Factory Pattern in Java](https://www.baeldung.com/java-abstract-factory-pattern) +- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern) +- [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) +- [Currying in Java](https://www.baeldung.com/java-currying) diff --git a/patterns/design-patterns/pom.xml b/patterns/design-patterns/pom.xml index ac201ad653..e6bff64f9e 100644 --- a/patterns/design-patterns/pom.xml +++ b/patterns/design-patterns/pom.xml @@ -48,6 +48,7 @@ ${grep4j.version} + UTF-8 1.8 diff --git a/core-java/src/main/java/com/baeldung/constructorsstaticfactorymethods/application/Application.java b/patterns/design-patterns/src/main/java/com/baeldung/constructorsstaticfactorymethods/application/Application.java similarity index 100% rename from core-java/src/main/java/com/baeldung/constructorsstaticfactorymethods/application/Application.java rename to patterns/design-patterns/src/main/java/com/baeldung/constructorsstaticfactorymethods/application/Application.java diff --git a/core-java/src/main/java/com/baeldung/constructorsstaticfactorymethods/entities/User.java b/patterns/design-patterns/src/main/java/com/baeldung/constructorsstaticfactorymethods/entities/User.java similarity index 100% rename from core-java/src/main/java/com/baeldung/constructorsstaticfactorymethods/entities/User.java rename to patterns/design-patterns/src/main/java/com/baeldung/constructorsstaticfactorymethods/entities/User.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java index 5b4bf08006..88e819c066 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java @@ -1,6 +1,5 @@ package com.baeldung.creational.abstractfactory; -public interface AbstractFactory { - Animal getAnimal(String toyType) ; - Color getColor(String colorType); +public interface AbstractFactory { + T create(String type) ; } \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java index 68759d5aff..c1501091c5 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java @@ -6,10 +6,10 @@ public class AbstractPatternDriver { //creating a brown toy dog abstractFactory = FactoryProvider.getFactory("Toy"); - Animal toy = abstractFactory.getAnimal("Dog"); + Animal toy =(Animal) abstractFactory.create("Dog"); abstractFactory = FactoryProvider.getFactory("Color"); - Color color = abstractFactory.getColor("Brown"); + Color color =(Color) abstractFactory.create("Brown"); String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound(); diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java index bbc3eb7a82..4b46261571 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java @@ -1,9 +1,9 @@ package com.baeldung.creational.abstractfactory; -public class AnimalFactory implements AbstractFactory { +public class AnimalFactory implements AbstractFactory { @Override - public Animal getAnimal(String animalType) { + public Animal create(String animalType) { if ("Dog".equalsIgnoreCase(animalType)) { return new Dog(); } else if ("Duck".equalsIgnoreCase(animalType)) { @@ -13,9 +13,4 @@ public class AnimalFactory implements AbstractFactory { return null; } - @Override - public Color getColor(String color) { - throw new UnsupportedOperationException(); - } - } diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java index 8b7e4f8086..3d9c5c18a3 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java @@ -1,9 +1,9 @@ package com.baeldung.creational.abstractfactory; -public class ColorFactory implements AbstractFactory { +public class ColorFactory implements AbstractFactory { @Override - public Color getColor(String colorType) { + public Color create(String colorType) { if ("Brown".equalsIgnoreCase(colorType)) { return new Brown(); } else if ("White".equalsIgnoreCase(colorType)) { @@ -13,9 +13,4 @@ public class ColorFactory implements AbstractFactory { return null; } - @Override - public Animal getAnimal(String toyType) { - throw new UnsupportedOperationException(); - } - } 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/core-java/src/test/java/com/baeldung/constructorsstaticfactorymethods/UserUnitTest.java b/patterns/design-patterns/src/test/java/com/baeldung/constructorsstaticfactorymethods/UserUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/constructorsstaticfactorymethods/UserUnitTest.java rename to patterns/design-patterns/src/test/java/com/baeldung/constructorsstaticfactorymethods/UserUnitTest.java diff --git a/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java b/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java index 6d1a4ad8fd..4f02249a4b 100644 --- a/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java +++ b/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java @@ -11,10 +11,10 @@ public class AbstractPatternIntegrationTest { //creating a brown toy dog abstractFactory = FactoryProvider.getFactory("Toy"); - Animal toy = abstractFactory.getAnimal("Dog"); + Animal toy = (Animal) abstractFactory.create("Dog"); abstractFactory = FactoryProvider.getFactory("Color"); - Color color = abstractFactory.getColor("Brown"); + Color color =(Color) abstractFactory.create("Brown"); String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound(); assertEquals("A Dog with brown color Barks", result); 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 diff --git a/patterns/dip/README.md b/patterns/dip/README.md new file mode 100644 index 0000000000..8876bbe766 --- /dev/null +++ b/patterns/dip/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [The Dependency Inversion Principle in Java](https://www.baeldung.com/java-dependency-inversion-principle) diff --git a/patterns/dip/pom.xml b/patterns/dip/pom.xml new file mode 100644 index 0000000000..bc793c0090 --- /dev/null +++ b/patterns/dip/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + com.baeldung.dip + dip + dip + 1.0-SNAPSHOT + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + + + junit + junit + ${junit.version} + test + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + UTF-8 + 11 + 11 + 3.12.1 + + + 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/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; +} diff --git a/patterns/front-controller/README.md b/patterns/front-controller/README.md new file mode 100644 index 0000000000..5f8cb5d568 --- /dev/null +++ b/patterns/front-controller/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern) diff --git a/patterns/intercepting-filter/README.md b/patterns/intercepting-filter/README.md new file mode 100644 index 0000000000..88b7f58469 --- /dev/null +++ b/patterns/intercepting-filter/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java) diff --git a/patterns/pom.xml b/patterns/pom.xml index bc1f5173e2..875af67d55 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 @@ -17,6 +17,9 @@ front-controller intercepting-filter design-patterns + design-patterns-2 + solid + dip @@ -48,9 +51,8 @@ - 3.1.0 3.0.0 9.4.0.v20161208 - \ No newline at end of file + diff --git a/patterns/solid/README.md b/patterns/solid/README.md new file mode 100644 index 0000000000..ddd2f78b7e --- /dev/null +++ b/patterns/solid/README.md @@ -0,0 +1,5 @@ +### Relevant Articles: + +- [A Solid Guide to Solid Principles](https://www.baeldung.com/solid-principles) + + diff --git a/patterns/solid/pom.xml b/patterns/solid/pom.xml new file mode 100644 index 0000000000..faf8bdc8d9 --- /dev/null +++ b/patterns/solid/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + com.baeldung + solid + solid + 1.0-SNAPSHOT + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + diff --git a/patterns/solid/src/main/java/com/baeldung/d/Keyboard.java b/patterns/solid/src/main/java/com/baeldung/d/Keyboard.java new file mode 100644 index 0000000000..cc6fc47d65 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/d/Keyboard.java @@ -0,0 +1,4 @@ +package com.baeldung.d; + +public interface Keyboard { +} diff --git a/patterns/solid/src/main/java/com/baeldung/d/Monitor.java b/patterns/solid/src/main/java/com/baeldung/d/Monitor.java new file mode 100644 index 0000000000..c0ab7a53b2 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/d/Monitor.java @@ -0,0 +1,6 @@ +package com.baeldung.d; + +public class Monitor { + + +} diff --git a/patterns/solid/src/main/java/com/baeldung/d/StandardKeyboard.java b/patterns/solid/src/main/java/com/baeldung/d/StandardKeyboard.java new file mode 100644 index 0000000000..cb0e229943 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/d/StandardKeyboard.java @@ -0,0 +1,5 @@ +package com.baeldung.d; + +public class StandardKeyboard implements Keyboard { + +} diff --git a/patterns/solid/src/main/java/com/baeldung/d/Windows98Machine.java b/patterns/solid/src/main/java/com/baeldung/d/Windows98Machine.java new file mode 100644 index 0000000000..4d6ead9aa2 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/d/Windows98Machine.java @@ -0,0 +1,15 @@ +package com.baeldung.d; + +public class Windows98Machine { + + private final StandardKeyboard keyboard; + private final Monitor monitor; + + public Windows98Machine() { + + monitor = new Monitor(); + keyboard = new StandardKeyboard(); + + } + +} diff --git a/patterns/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java b/patterns/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java new file mode 100644 index 0000000000..2a6fd74a41 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java @@ -0,0 +1,12 @@ +package com.baeldung.d; + +public class Windows98MachineDI { + + private final Keyboard keyboard; + private final Monitor monitor; + + public Windows98MachineDI(Keyboard keyboard, Monitor monitor) { + this.keyboard = keyboard; + this.monitor = monitor; + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/BearCarer.java b/patterns/solid/src/main/java/com/baeldung/i/BearCarer.java new file mode 100644 index 0000000000..3d69211674 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/BearCarer.java @@ -0,0 +1,12 @@ +package com.baeldung.i; + +public class BearCarer implements BearCleaner, BearFeeder { + + public void washTheBear() { + //I think we missed a spot.. + } + + public void feedTheBear() { + //Tuna tuesdays.. + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/BearCleaner.java b/patterns/solid/src/main/java/com/baeldung/i/BearCleaner.java new file mode 100644 index 0000000000..e2b71b2ce8 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/BearCleaner.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearCleaner { + void washTheBear(); +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/BearFeeder.java b/patterns/solid/src/main/java/com/baeldung/i/BearFeeder.java new file mode 100644 index 0000000000..5d0ba7cd29 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/BearFeeder.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearFeeder { + void feedTheBear(); +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/BearKeeper.java b/patterns/solid/src/main/java/com/baeldung/i/BearKeeper.java new file mode 100644 index 0000000000..f09774a5ff --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/BearKeeper.java @@ -0,0 +1,9 @@ +package com.baeldung.i; + +public interface BearKeeper { + + void washTheBear(); + void feedTheBear(); + void petTheBear(); + +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/BearPetter.java b/patterns/solid/src/main/java/com/baeldung/i/BearPetter.java new file mode 100644 index 0000000000..a913cf3d8a --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/BearPetter.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearPetter { + void petTheBear(); +} diff --git a/patterns/solid/src/main/java/com/baeldung/i/CrazyPerson.java b/patterns/solid/src/main/java/com/baeldung/i/CrazyPerson.java new file mode 100644 index 0000000000..aae0d4c11b --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/i/CrazyPerson.java @@ -0,0 +1,8 @@ +package com.baeldung.i; + +public class CrazyPerson implements BearPetter { + + public void petTheBear() { + //Good luck with that! + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/l/Car.java b/patterns/solid/src/main/java/com/baeldung/l/Car.java new file mode 100644 index 0000000000..b3481f894a --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/l/Car.java @@ -0,0 +1,8 @@ +package com.baeldung.l; + +public interface Car { + + void turnOnEngine(); + void accelerate(); + +} diff --git a/patterns/solid/src/main/java/com/baeldung/l/ElectricCar.java b/patterns/solid/src/main/java/com/baeldung/l/ElectricCar.java new file mode 100644 index 0000000000..fd919c5659 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/l/ElectricCar.java @@ -0,0 +1,12 @@ +package com.baeldung.l; + +public class ElectricCar implements Car { + + public void turnOnEngine() { + throw new AssertionError("I don't have an engine!"); + } + + public void accelerate() { + //this acceleration is crazy! + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/l/Engine.java b/patterns/solid/src/main/java/com/baeldung/l/Engine.java new file mode 100644 index 0000000000..a8e38b8877 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/l/Engine.java @@ -0,0 +1,13 @@ +package com.baeldung.l; + +public class Engine { + + public void on(){ + //vroom. + } + + public void powerOn(int amount){ + //do something + } + +} diff --git a/patterns/solid/src/main/java/com/baeldung/l/MotorCar.java b/patterns/solid/src/main/java/com/baeldung/l/MotorCar.java new file mode 100644 index 0000000000..638f315475 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/l/MotorCar.java @@ -0,0 +1,18 @@ +package com.baeldung.l; + +public class MotorCar implements Car { + + private Engine engine; + + //Constructors, getters + setters + + public void turnOnEngine() { + //turn on the engine! + engine.on(); + } + + public void accelerate() { + //move forward! + engine.powerOn(1000); + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/o/Guitar.java b/patterns/solid/src/main/java/com/baeldung/o/Guitar.java new file mode 100644 index 0000000000..baab006b5b --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/o/Guitar.java @@ -0,0 +1,10 @@ +package com.baeldung.o; + +public class Guitar { + + private String make; + private String model; + private int volume; + + //Constructors, getters & setters +} diff --git a/patterns/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java b/patterns/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java new file mode 100644 index 0000000000..b69e3be74a --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java @@ -0,0 +1,9 @@ +package com.baeldung.o; + +public class SuperCoolGuitarWithFlames extends Guitar { + + private String flameColour; + + //constructor, getters + setters + +} diff --git a/patterns/solid/src/main/java/com/baeldung/s/BadBook.java b/patterns/solid/src/main/java/com/baeldung/s/BadBook.java new file mode 100644 index 0000000000..03c8fcd488 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/s/BadBook.java @@ -0,0 +1,27 @@ +package com.baeldung.s; + +public class BadBook { + + private String name; + private String author; + private String text; + + //constructor, getters and setters + + + //methods that directly relate to the book properties + public String replaceWordInText(String word){ + return text.replaceAll(word, text); + } + + public boolean isWordInText(String word){ + return text.contains(word); + } + + //methods for outputting text to console - should this really be here? + void printTextToConsole(){ + //our code for formatting and printing the text + } + + +} diff --git a/patterns/solid/src/main/java/com/baeldung/s/BookPrinter.java b/patterns/solid/src/main/java/com/baeldung/s/BookPrinter.java new file mode 100644 index 0000000000..0c8ef62e01 --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/s/BookPrinter.java @@ -0,0 +1,13 @@ +package com.baeldung.s; + +public class BookPrinter { + + //methods for outputting text + void printTextToConsole(String text){ + //our code for formatting and printing the text + } + + void printTextToAnotherMedium(String text){ + //code for writing to any other location.. + } +} diff --git a/patterns/solid/src/main/java/com/baeldung/s/GoodBook.java b/patterns/solid/src/main/java/com/baeldung/s/GoodBook.java new file mode 100644 index 0000000000..b0993aca2b --- /dev/null +++ b/patterns/solid/src/main/java/com/baeldung/s/GoodBook.java @@ -0,0 +1,20 @@ +package com.baeldung.s; + +public class GoodBook { + + private String name; + private String author; + private String text; + + //constructor, getters and setters + + //methods that directly relate to the book properties + public String replaceWordInText(String word){ + return text.replaceAll(word, text); + } + + public boolean isWordInText(String word){ + return text.contains(word); + } + +} diff --git a/performance-tests/pom.xml b/performance-tests/pom.xml index 7d77c2a0e3..d7738780bf 100644 --- a/performance-tests/pom.xml +++ b/performance-tests/pom.xml @@ -46,12 +46,12 @@ org.openjdk.jmh jmh-core - ${jmh.version} + ${jmh-core.version} org.openjdk.jmh jmh-generator-annprocess - ${jmh.version} + ${jmh-generator.version} @@ -85,7 +85,6 @@ 1.2.0.Final 1.1.0 1.6.0.1 - 1.20 1.2.0.Final diff --git a/persistence-modules/README.md b/persistence-modules/README.md deleted file mode 100644 index 87dc9522fd..0000000000 --- a/persistence-modules/README.md +++ /dev/null @@ -1,13 +0,0 @@ - -## Persistence Modules - - -### Relevant Articles: - -- [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search) -- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring) -- [Introduction to Lettuce – the Java Redis Client](http://www.baeldung.com/java-redis-lettuce) -- [A Guide to Jdbi](http://www.baeldung.com/jdbi) -- [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking) -- [Get All Data from a Table with Hibernate](https://www.baeldung.com/hibernate-select-all) -- [Spring Data with Reactive Cassandra](https://www.baeldung.com/spring-data-cassandra-reactive) diff --git a/persistence-modules/activejdbc/pom.xml b/persistence-modules/activejdbc/pom.xml index 6a29f14ced..45a618b840 100644 --- a/persistence-modules/activejdbc/pom.xml +++ b/persistence-modules/activejdbc/pom.xml @@ -3,8 +3,8 @@ 4.0.0 activejdbc 1.0-SNAPSHOT - jar activejdbc + jar http://maven.apache.org diff --git a/persistence-modules/apache-cayenne/pom.xml b/persistence-modules/apache-cayenne/pom.xml index d0c6d1f2b2..776b2b5233 100644 --- a/persistence-modules/apache-cayenne/pom.xml +++ b/persistence-modules/apache-cayenne/pom.xml @@ -2,11 +2,10 @@ 4.0.0 - apache-cayenne 0.0.1-SNAPSHOT - jar apache-cayenne + jar Introduction to Apache Cayenne diff --git a/persistence-modules/core-java-persistence/README.md b/persistence-modules/core-java-persistence/README.md index ca0ce81eef..1187cc15c4 100644 --- a/persistence-modules/core-java-persistence/README.md +++ b/persistence-modules/core-java-persistence/README.md @@ -7,3 +7,5 @@ - [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) +- [Types of SQL Joins](https://www.baeldung.com/sql-joins) diff --git a/persistence-modules/core-java-persistence/pom.xml b/persistence-modules/core-java-persistence/pom.xml index f012d60ee6..2760489ce1 100644 --- a/persistence-modules/core-java-persistence/pom.xml +++ b/persistence-modules/core-java-persistence/pom.xml @@ -4,15 +4,23 @@ com.baeldung.core-java-persistence core-java-persistence 0.1.0-SNAPSHOT - jar core-java-persistence + jar + com.baeldung parent-java 0.0.1-SNAPSHOT ../../parent-java + + + org.postgresql + postgresql + ${postgresql.version} + test + org.assertj assertj-core @@ -22,7 +30,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.apache.commons @@ -50,6 +58,7 @@ ${springframework.boot.spring-boot-starter.version} + core-java-persistence @@ -58,14 +67,17 @@ true - + + + 42.2.5.jre7 + 8.0.15 3.10.0 - 1.4.197 2.4.0 3.2.0 0.9.5.2 1.5.8.RELEASE 4.3.4.RELEASE + \ No newline at end of file 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..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 @@ -1,5 +1,7 @@ package com.baeldung.jdbc; +import java.util.Objects; + public class Employee { private int id; private String name; @@ -48,4 +50,21 @@ public class Employee { 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); + } + } diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java new file mode 100644 index 0000000000..5ce196ee47 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java @@ -0,0 +1,41 @@ +package com.baeldung.jdbc.joins; + +class ArticleWithAuthor { + + private String title; + + private String authorFirstName; + + private String authorLastName; + + public ArticleWithAuthor(String title, String authorFirstName, String authorLastName) { + this.title = title; + this.authorFirstName = authorFirstName; + this.authorLastName = authorLastName; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthorFirstName() { + return authorFirstName; + } + + public void setAuthorFirstName(String authorFirstName) { + this.authorFirstName = authorFirstName; + } + + public String getAuthorLastName() { + return authorLastName; + } + + public void setAuthorLastName(String authorLastName) { + this.authorLastName = authorLastName; + } + +} diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java new file mode 100644 index 0000000000..55f03d99ec --- /dev/null +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java @@ -0,0 +1,61 @@ +package com.baeldung.jdbc.joins; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +class ArticleWithAuthorDAO { + + private static final String QUERY_TEMPLATE = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME FROM ARTICLE %s AUTHOR ON AUTHOR.id=ARTICLE.AUTHOR_ID"; + private final Connection connection; + + ArticleWithAuthorDAO(Connection connection) { + this.connection = connection; + } + + List articleInnerJoinAuthor() { + String query = String.format(QUERY_TEMPLATE, "INNER JOIN"); + return executeQuery(query); + } + + List articleLeftJoinAuthor() { + String query = String.format(QUERY_TEMPLATE, "LEFT JOIN"); + return executeQuery(query); + } + + List articleRightJoinAuthor() { + String query = String.format(QUERY_TEMPLATE, "RIGHT JOIN"); + return executeQuery(query); + } + + List articleFullJoinAuthor() { + String query = String.format(QUERY_TEMPLATE, "FULL JOIN"); + return executeQuery(query); + } + + private List executeQuery(String query) { + try (Statement statement = connection.createStatement()) { + ResultSet resultSet = statement.executeQuery(query); + return mapToList(resultSet); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + private List mapToList(ResultSet resultSet) throws SQLException { + List list = new ArrayList<>(); + while (resultSet.next()) { + ArticleWithAuthor articleWithAuthor = new ArticleWithAuthor( + resultSet.getString("TITLE"), + resultSet.getString("FIRST_NAME"), + resultSet.getString("LAST_NAME") + ); + list.add(articleWithAuthor); + } + return list; + } +} 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..4e10f8bd43 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -0,0 +1,359 @@ +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; + +import junit.framework.Assert; + +@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_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); + } + + @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); + } + + @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); + } + + 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", 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); + } + + 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); + } + + 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); + } + } + + assertEquals("Several Navigation Options", updatedEmployee1, firstEmployee); + } + + @Test + public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { + 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); + ResultSet rs = pstmt.executeQuery("select * from employees"); + while (rs.next()) { + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("position", "Senior Engineer"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } + } + rs.last(); + } + + assertEquals("Update using closed cursor", "Senior Engineer", employee.getPosition()); + } + + @Test + public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { + 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); + ResultSet rs = pstmt.executeQuery("select * from employees"); + while (rs.next()) { + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("name", "John Doe"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } + } + rs.last(); + } + + 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(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", 1, 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()) { + + Assert.assertEquals(1100.0, rs.getDouble("salary")); + + rs.updateDouble("salary", 1200.0); + rs.updateRow(); + + 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"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + } + + @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 : ", 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); + } + } + + assertEquals("column count", 4, columnCount); + } + + @Test + 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_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + pstmt.setFetchSize(1); + 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(2, 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(); + } +} \ No newline at end of file diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOLiveTest.java new file mode 100644 index 0000000000..3f69a0e333 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOLiveTest.java @@ -0,0 +1,89 @@ +package com.baeldung.jdbc.joins; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ArticleWithAuthorDAOLiveTest { + private Connection connection; + + private ArticleWithAuthorDAO articleWithAuthorDAO; + + @Before + public void setup() throws ClassNotFoundException, SQLException { + Class.forName("org.postgresql.Driver"); + connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/myDb", "user", "pass"); + articleWithAuthorDAO = new ArticleWithAuthorDAO(connection); + Statement statement = connection.createStatement(); + String createAuthorSql = "CREATE TABLE IF NOT EXISTS AUTHOR (ID int NOT NULL PRIMARY KEY, FIRST_NAME varchar(255), LAST_NAME varchar(255));"; + String createArticleSql = "CREATE TABLE IF NOT EXISTS ARTICLE (ID int NOT NULL PRIMARY KEY, TITLE varchar(255) NOT NULL, AUTHOR_ID int, FOREIGN KEY(AUTHOR_ID) REFERENCES AUTHOR(ID));"; + statement.execute(createAuthorSql); + statement.execute(createArticleSql); + + insertTestData(statement); + } + + @Test + public void whenQueryWithInnerJoin_thenShouldReturnProperRows() { + List articleWithAuthorList = articleWithAuthorDAO.articleInnerJoinAuthor(); + + assertThat(articleWithAuthorList).hasSize(4); + assertThat(articleWithAuthorList).noneMatch(row -> row.getAuthorFirstName() == null || row.getTitle() == null); + } + + @Test + public void whenQueryWithLeftJoin_thenShouldReturnProperRows() { + List articleWithAuthorList = articleWithAuthorDAO.articleLeftJoinAuthor(); + + assertThat(articleWithAuthorList).hasSize(5); + assertThat(articleWithAuthorList).anyMatch(row -> row.getAuthorFirstName() == null); + } + + @Test + public void whenQueryWithRightJoin_thenShouldReturnProperRows() { + List articleWithAuthorList = articleWithAuthorDAO.articleRightJoinAuthor(); + + assertThat(articleWithAuthorList).hasSize(5); + assertThat(articleWithAuthorList).anyMatch(row -> row.getTitle() == null); + } + + @Test + public void whenQueryWithFullJoin_thenShouldReturnProperRows() { + List articleWithAuthorList = articleWithAuthorDAO.articleFullJoinAuthor(); + + assertThat(articleWithAuthorList).hasSize(6); + assertThat(articleWithAuthorList).anyMatch(row -> row.getTitle() == null); + assertThat(articleWithAuthorList).anyMatch(row -> row.getAuthorFirstName() == null); + } + + @After + public void cleanup() throws SQLException { + connection.createStatement().execute("DROP TABLE ARTICLE"); + connection.createStatement().execute("DROP TABLE AUTHOR"); + connection.close(); + } + + public void insertTestData(Statement statement) throws SQLException { + String insertAuthors = "INSERT INTO AUTHOR VALUES " + + "(1, 'Siena', 'Kerr')," + + "(2, 'Daniele', 'Ferguson')," + + "(3, 'Luciano', 'Wise')," + + "(4, 'Jonas', 'Lugo');"; + String insertArticles = "INSERT INTO ARTICLE VALUES " + + "(1, 'First steps in Java', 1)," + + "(2, 'SpringBoot tutorial', 1)," + + "(3, 'Java 12 insights', null)," + + "(4, 'SQL JOINS', 2)," + + "(5, 'Introduction to Spring Security', 3);"; + statement.execute(insertAuthors); + statement.execute(insertArticles); + } +} diff --git a/persistence-modules/deltaspike/pom.xml b/persistence-modules/deltaspike/pom.xml index b798d2f39e..4dcef07695 100644 --- a/persistence-modules/deltaspike/pom.xml +++ b/persistence-modules/deltaspike/pom.xml @@ -5,8 +5,8 @@ com.baeldung deltaspike 1.0 - war deltaspike + war A starter Java EE 7 webapp which uses DeltaSpike http://wildfly.org @@ -317,7 +317,6 @@ 2.6 1.1.3 1.2.5.Final-redhat-1 - 1.4.197 3.5 diff --git a/persistence-modules/elasticsearch/.gitignore b/persistence-modules/elasticsearch/.gitignore new file mode 100644 index 0000000000..153c9335eb --- /dev/null +++ b/persistence-modules/elasticsearch/.gitignore @@ -0,0 +1,29 @@ +HELP.md +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +/build/ + +### VS Code ### +.vscode/ diff --git a/persistence-modules/elasticsearch/README.md b/persistence-modules/elasticsearch/README.md new file mode 100644 index 0000000000..691e855314 --- /dev/null +++ b/persistence-modules/elasticsearch/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Jest – Elasticsearch Java Client](https://www.baeldung.com/elasticsearch-jest) diff --git a/persistence-modules/elasticsearch/pom.xml b/persistence-modules/elasticsearch/pom.xml new file mode 100644 index 0000000000..f7bfdb44de --- /dev/null +++ b/persistence-modules/elasticsearch/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + com.baeldung + elasticsearch + 0.0.1-SNAPSHOT + elasticsearch + Demo project for Java Elasticsearch libraries + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + + io.searchbox + jest + ${jest.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + 6.3.1 + + diff --git a/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/Employee.java b/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/Employee.java new file mode 100644 index 0000000000..6f28a42a9c --- /dev/null +++ b/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/Employee.java @@ -0,0 +1,42 @@ +package com.baeldung.jest; + +import java.util.List; + +public class Employee { + String name; + String title; + List skills; + int yearsOfService; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getSkills() { + return skills; + } + + public void setSkills(List skills) { + this.skills = skills; + } + + public int getYearsOfService() { + return yearsOfService; + } + + public void setYearsOfService(int yearsOfService) { + this.yearsOfService = yearsOfService; + } +} diff --git a/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/JestDemoApplication.java b/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/JestDemoApplication.java new file mode 100644 index 0000000000..91e499da2e --- /dev/null +++ b/persistence-modules/elasticsearch/src/main/java/com/baeldung/jest/JestDemoApplication.java @@ -0,0 +1,174 @@ +package com.baeldung.jest; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.searchbox.client.JestClient; +import io.searchbox.client.JestClientFactory; +import io.searchbox.client.JestResult; +import io.searchbox.client.JestResultHandler; +import io.searchbox.client.config.HttpClientConfig; +import io.searchbox.core.*; +import io.searchbox.indices.CreateIndex; +import io.searchbox.indices.IndicesExists; +import io.searchbox.indices.aliases.AddAliasMapping; +import io.searchbox.indices.aliases.ModifyAliases; +import io.searchbox.indices.aliases.RemoveAliasMapping; + +import java.io.IOException; +import java.util.*; + +public class JestDemoApplication { + + public static void main(String[] args) throws IOException { + + // Demo the JestClient + JestClient jestClient = jestClient(); + + // Check an index + JestResult result = jestClient.execute(new IndicesExists.Builder("employees").build()); + if(!result.isSucceeded()) { + System.out.println(result.getErrorMessage()); + } + + // Create an index + jestClient.execute(new CreateIndex.Builder("employees").build()); + + // Create an index with options + Map settings = new HashMap<>(); + settings.put("number_of_shards", 11); + settings.put("number_of_replicas", 2); + jestClient.execute(new CreateIndex.Builder("employees").settings(settings).build()); + + // Create an alias, then remove it + jestClient.execute(new ModifyAliases.Builder( + new AddAliasMapping.Builder( + "employees", + "e") + .build()) + .build()); + JestResult jestResult = jestClient.execute(new ModifyAliases.Builder( + new RemoveAliasMapping.Builder( + "employees", + "e") + .build()) + .build()); + + if(jestResult.isSucceeded()) { + System.out.println("Success!"); + } + else { + System.out.println(jestResult.getErrorMessage()); + } + + // Sample JSON for indexing + + // { + // "name": "Michael Pratt", + // "title": "Java Developer", + // "skills": ["java", "spring", "elasticsearch"], + // "yearsOfService": 2 + // } + + // Index a document from String + ObjectMapper mapper = new ObjectMapper(); + JsonNode employeeJsonNode = mapper.createObjectNode() + .put("name", "Michael Pratt") + .put("title", "Java Developer") + .put("yearsOfService", 2) + .set("skills", mapper.createArrayNode() + .add("java") + .add("spring") + .add("elasticsearch")); + jestClient.execute(new Index.Builder(employeeJsonNode.toString()).index("employees").build()); + + // Index a document from Map + Map employeeHashMap = new LinkedHashMap<>(); + employeeHashMap.put("name", "Michael Pratt"); + employeeHashMap.put("title", "Java Developer"); + employeeHashMap.put("yearsOfService", 2); + employeeHashMap.put("skills", Arrays.asList("java", "spring", "elasticsearch")); + jestClient.execute(new Index.Builder(employeeHashMap).index("employees").build()); + + // Index a document from POJO + Employee employee = new Employee(); + employee.setName("Michael Pratt"); + employee.setTitle("Java Developer"); + employee.setYearsOfService(2); + employee.setSkills(Arrays.asList("java", "spring", "elasticsearch")); + jestClient.execute(new Index.Builder(employee).index("employees").build()); + + // Read document by ID + Employee getResult = jestClient.execute(new Get.Builder("employees", "1").build()).getSourceAsObject(Employee.class); + + // Search documents + String search = "{\n" + + " \"query\": {\n" + + " \"bool\": {\n" + + " \"must\": [\n" + + " { \"match\": { \"name\": \"Michael Pratt\" }}\n" + + " ]\n" + + " }\n" + + " }\n" + + "}"; + List> searchResults = + jestClient.execute(new Search.Builder(search).build()) + .getHits(Employee.class); + + searchResults.forEach(hit -> { + System.out.println(String.format("Document %s has score %s", hit.id, hit.score)); + }); + + // Update document + employee.setYearsOfService(3); + jestClient.execute(new Update.Builder(employee).index("employees").id("1").build()); + + // Delete documents + jestClient.execute(new Delete.Builder("2") .index("employees") .build()); + + // Bulk operations + Employee employeeObject1 = new Employee(); + employee.setName("John Smith"); + employee.setTitle("Python Developer"); + employee.setYearsOfService(10); + employee.setSkills(Arrays.asList("python")); + + Employee employeeObject2 = new Employee(); + employee.setName("Kate Smith"); + employee.setTitle("Senior JavaScript Developer"); + employee.setYearsOfService(10); + employee.setSkills(Arrays.asList("javascript", "angular")); + + jestClient.execute(new Bulk.Builder().defaultIndex("employees") + .addAction(new Index.Builder(employeeObject1).build()) + .addAction(new Index.Builder(employeeObject2).build()) + .addAction(new Delete.Builder("3").build()) .build()); + + // Async operations + Employee employeeObject3 = new Employee(); + employee.setName("Jane Doe"); + employee.setTitle("Manager"); + employee.setYearsOfService(20); + employee.setSkills(Arrays.asList("managing")); + + jestClient.executeAsync( new Index.Builder(employeeObject3).build(), new JestResultHandler() { + @Override public void completed(JestResult result) { + // handle result + } + @Override public void failed(Exception ex) { + // handle exception + } + }); + } + + private static JestClient jestClient() + { + JestClientFactory factory = new JestClientFactory(); + factory.setHttpClientConfig( + new HttpClientConfig.Builder("http://localhost:9200") + .multiThreaded(true) + .defaultMaxTotalConnectionPerRoute(2) + .maxTotalConnection(20) + .build()); + return factory.getObject(); + } +} diff --git a/persistence-modules/flyway/pom.xml b/persistence-modules/flyway/pom.xml index 237b426521..99549ee3fc 100644 --- a/persistence-modules/flyway/pom.xml +++ b/persistence-modules/flyway/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 flyway - jar flyway + jar Flyway Callbacks Demo @@ -65,7 +65,6 @@ 5.0.2 5.0.2 - 1.4.195 diff --git a/persistence-modules/hibernate-mapping/README.md b/persistence-modules/hibernate-mapping/README.md new file mode 100644 index 0000000000..0df13653b9 --- /dev/null +++ b/persistence-modules/hibernate-mapping/README.md @@ -0,0 +1,6 @@ + +### Relevant Articles: + +- [Persisting Maps with Hibernate](https://www.baeldung.com/hibernate-persisting-maps) +- [Difference Between @Size, @Length, and @Column(length=value)](https://www.baeldung.com/jpa-size-length-column-differences) +- [Hibernate Validator Specific Constraints](https://www.baeldung.com/hibernate-validator-constraints) diff --git a/persistence-modules/hibernate-mapping/pom.xml b/persistence-modules/hibernate-mapping/pom.xml new file mode 100644 index 0000000000..509c54ca75 --- /dev/null +++ b/persistence-modules/hibernate-mapping/pom.xml @@ -0,0 +1,76 @@ + + + hibernate-mapping + 1.0.0-SNAPSHOT + 4.0.0 + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + .. + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + com.h2database + h2 + ${h2.version} + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + org.glassfish + javax.el + ${org.glassfish.javax.el.version} + + + javax.money + money-api + ${money-api.version} + + + org.javamoney + moneta + ${moneta.version} + pom + + + + + hibernate-mapping + + + src/test/resources + true + + + + + + 5.3.10.Final + 3.8.0 + 6.0.16.Final + 3.0.1-b11 + 1.0.3 + 1.3 + + + diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java new file mode 100644 index 0000000000..7de13db8d3 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java @@ -0,0 +1,60 @@ +package com.baeldung.hibernate; + +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateUtil { + + private HibernateUtil() { + } + + public static SessionFactory getSessionFactory(Strategy strategy) { + return buildSessionFactory(strategy); + } + + private static SessionFactory buildSessionFactory(Strategy strategy) { + try { + ServiceRegistry serviceRegistry = configureServiceRegistry(); + + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + + for (Class entityClass : strategy.getEntityClasses()) { + metadataSources.addAnnotatedClass(entityClass); + } + + Metadata metadata = metadataSources.getMetadataBuilder() + .build(); + + return metadata.getSessionFactoryBuilder() + .build(); + } catch (IOException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + + private static ServiceRegistry configureServiceRegistry() throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource("hibernate.properties"); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java new file mode 100644 index 0000000000..b0bc095b43 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java @@ -0,0 +1,31 @@ +package com.baeldung.hibernate; + + +import java.util.Arrays; +import java.util.List; + +public enum Strategy { + //See that the classes belongs to different packages + MAP_KEY_COLUMN_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeycolumn.Order.class, + com.baeldung.hibernate.basicannotation.Course.class)), + MAP_KEY_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkey.Item.class, + com.baeldung.hibernate.persistmaps.mapkey.Order.class,com.baeldung.hibernate.persistmaps.mapkey.User.class)), + MAP_KEY_JOIN_COLUMN_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Seller.class, + com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Item.class, + com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Order.class)), + MAP_KEY_ENUMERATED_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeyenumerated.Order.class, + com.baeldung.hibernate.persistmaps.mapkey.Item.class)), + MAP_KEY_TEMPORAL_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeytemporal.Order.class, + com.baeldung.hibernate.persistmaps.mapkey.Item.class)); + + + private List> entityClasses; + + Strategy(List> entityClasses) { + this.entityClasses = entityClasses; + } + + public List> getEntityClasses() { + return entityClasses; + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/basicannotation/Course.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/basicannotation/Course.java new file mode 100644 index 0000000000..e816fb0176 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/basicannotation/Course.java @@ -0,0 +1,34 @@ +package com.baeldung.hibernate.basicannotation; + +import javax.persistence.Basic; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Course { + + @Id + private int id; + + @Basic(optional = false, fetch = FetchType.LAZY) + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java new file mode 100644 index 0000000000..b7f3cef9a2 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java @@ -0,0 +1,6 @@ +package com.baeldung.hibernate.persistmaps; + +public enum ItemType { + JEANS, + TSHIRTS +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java new file mode 100644 index 0000000000..385ffe93ea --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java @@ -0,0 +1,95 @@ +package com.baeldung.hibernate.persistmaps.mapkey; + +import com.baeldung.hibernate.persistmaps.ItemType; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import java.util.Date; +import java.util.Objects; + +@Entity +@Table(name = "item") +public class Item { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @Column(name = "name") + private String itemName; + + @Column(name = "price") + private double itemPrice; + + @Enumerated(EnumType.STRING) + @Column(name = "item_type") + private ItemType itemType; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "created_on") + private Date createdOn; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getItemName() { + return itemName; + } + + public void setItemName(String itemName) { + this.itemName = itemName; + } + + public double getItemPrice() { + return itemPrice; + } + + public void setItemPrice(double itemPrice) { + this.itemPrice = itemPrice; + } + + public ItemType getItemType() { + return itemType; + } + + public void setItemType(ItemType itemType) { + this.itemType = itemType; + } + + public Date getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(Date createdOn) { + this.createdOn = createdOn; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Item item = (Item) o; + return id == item.id && + Double.compare(item.itemPrice, itemPrice) == 0 && + Objects.equals(itemName, item.itemName) && + itemType == item.itemType && + Objects.equals(createdOn, item.createdOn); + } + + @Override + public int hashCode() { + return Objects.hash(id, itemName, itemPrice, itemType, createdOn); + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java new file mode 100644 index 0000000000..8409cacd6b --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java @@ -0,0 +1,44 @@ +package com.baeldung.hibernate.persistmaps.mapkey; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.MapKey; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import java.util.Map; + +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) + @MapKey(name = "itemName") + private Map itemMap; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getItemMap() { + return itemMap; + } + + public void setItemMap(Map itemMap) { + this.itemMap = itemMap; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/User.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/User.java new file mode 100644 index 0000000000..b2ee7e85fe --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/User.java @@ -0,0 +1,68 @@ +package com.baeldung.hibernate.persistmaps.mapkey; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.validation.constraints.Size; +import javax.money.MonetaryAmount; + +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.CreditCardNumber; +import org.hibernate.validator.constraints.Currency; + +@Entity +public class User { + @Id + @Column(length = 3) + private String firstName; + + @Size(min = 3, max = 15) + private String middleName; + + @Length(min = 3, max = 15) + private String lastName; + + @Column(length = 5) + @Size(min = 3, max = 5) + private String city; + + public User(String firstName, String middleName, String lastName, String city) { + super(); + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + this.city = city; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middletName) { + this.middleName = middletName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java new file mode 100644 index 0000000000..fa092060da --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java @@ -0,0 +1,43 @@ +package com.baeldung.hibernate.persistmaps.mapkeycolumn; + +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapKeyColumn; +import javax.persistence.Table; +import java.util.Map; + +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @ElementCollection + @CollectionTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}) + @MapKeyColumn(name = "item_name") + @Column(name = "price") + private Map itemPriceMap; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getItemPriceMap() { + return itemPriceMap; + } + + public void setItemPriceMap(Map itemPriceMap) { + this.itemPriceMap = itemPriceMap; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java new file mode 100644 index 0000000000..e1f62599b8 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java @@ -0,0 +1,48 @@ +package com.baeldung.hibernate.persistmaps.mapkeyenumerated; + +import com.baeldung.hibernate.persistmaps.ItemType; +import com.baeldung.hibernate.persistmaps.mapkey.Item; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.MapKeyEnumerated; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import java.util.Map; + +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) + @MapKeyEnumerated(EnumType.STRING) + private Map itemMap; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getItemMap() { + return itemMap; + } + + public void setItemMap(Map itemMap) { + this.itemMap = itemMap; + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java new file mode 100644 index 0000000000..97bbd5b539 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java @@ -0,0 +1,112 @@ +package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn; + +import com.baeldung.hibernate.persistmaps.ItemType; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import java.util.Date; +import java.util.Objects; + +@Entity +@Table(name = "item") +public class Item { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @Column(name = "name") + private String itemName; + + @Column(name = "price") + private double itemPrice; + + @Column(name = "item_type") + @Enumerated(EnumType.STRING) + private ItemType itemType; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "created_on") + private Date createdOn; + + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "seller_id") + private Seller seller; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getItemName() { + return itemName; + } + + public void setItemName(String itemName) { + this.itemName = itemName; + } + + public double getItemPrice() { + return itemPrice; + } + + public void setItemPrice(double itemPrice) { + this.itemPrice = itemPrice; + } + + public ItemType getItemType() { + return itemType; + } + + public void setItemType(ItemType itemType) { + this.itemType = itemType; + } + + public Date getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(Date createdOn) { + this.createdOn = createdOn; + } + + public Seller getSeller() { + return seller; + } + + public void setSeller(Seller seller) { + this.seller = seller; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Item item = (Item) o; + return id == item.id && + Double.compare(item.itemPrice, itemPrice) == 0 && + Objects.equals(itemName, item.itemName) && + itemType == item.itemType && + Objects.equals(createdOn, item.createdOn) && + Objects.equals(seller, item.seller); + } + + @Override + public int hashCode() { + + return Objects.hash(id, itemName, itemPrice, itemType, createdOn, seller); + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java new file mode 100644 index 0000000000..d680d84501 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java @@ -0,0 +1,44 @@ +package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.MapKeyJoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import java.util.Map; + +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) + @MapKeyJoinColumn(name = "seller_id") + private Map sellerItemMap; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getSellerItemMap() { + return sellerItemMap; + } + + public void setSellerItemMap(Map sellerItemMap) { + this.sellerItemMap = sellerItemMap; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java new file mode 100644 index 0000000000..15b08e9fe6 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java @@ -0,0 +1,51 @@ +package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Objects; + +@Entity +@Table(name = "seller") +public class Seller { + + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @Column(name = "name") + private String sellerName; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getSellerName() { + return sellerName; + } + + public void setSellerName(String sellerName) { + this.sellerName = sellerName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Seller seller = (Seller) o; + return Objects.equals(sellerName, seller.sellerName); + } + + @Override + public int hashCode() { + + return Objects.hash(sellerName); + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java new file mode 100644 index 0000000000..be602c1e9f --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java @@ -0,0 +1,48 @@ +package com.baeldung.hibernate.persistmaps.mapkeytemporal; + +import com.baeldung.hibernate.persistmaps.mapkey.Item; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.MapKeyTemporal; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.TemporalType; +import java.util.Date; +import java.util.Map; + +@Entity +@Table(name = "orders") +public class Order { + @Id + @GeneratedValue + @Column(name = "id") + private int id; + + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) + @MapKeyTemporal(TemporalType.TIMESTAMP) + private Map itemMap; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getItemMap() { + return itemMap; + } + + public void setItemMap(Map itemMap) { + this.itemMap = itemMap; + } +} diff --git a/persistence-modules/hibernate-mapping/src/main/resources/logback.xml b/persistence-modules/hibernate-mapping/src/main/resources/logback.xml new file mode 100644 index 0000000000..26beb6d5b4 --- /dev/null +++ b/persistence-modules/hibernate-mapping/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/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/basicannotation/BasicAnnotationIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/basicannotation/BasicAnnotationIntegrationTest.java new file mode 100644 index 0000000000..930bea60c5 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/basicannotation/BasicAnnotationIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.hibernate.basicannotation; + +import java.io.IOException; + +import javax.persistence.PersistenceException; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; + +public class BasicAnnotationIntegrationTest { + + private static SessionFactory sessionFactory; + private Session session; + private Transaction transaction; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_COLUMN_BASED); + } + + @Before + public void setUp() throws IOException { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + } + + @After + public void tearDown() { + transaction.rollback(); + session.close(); + } + + @Test + public void givenACourse_whenCourseNamePresent_shouldPersist() { + Course course = new Course(); + course.setName("Computers"); + + session.save(course); + session.flush(); + session.clear(); + + } + + @Test(expected = PersistenceException.class) + public void givenACourse_whenCourseNameAbsent_shouldFail() { + Course course = new Course(); + + session.save(course); + session.flush(); + session.clear(); + } +} diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java new file mode 100644 index 0000000000..acd77ee382 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java @@ -0,0 +1,79 @@ +package com.baeldung.hibernate.persistmaps; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkeycolumn.Order; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MapKeyColumnIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_COLUMN_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenData_whenInsertUsingMapKeyColumn_thenPersistMap() { + Map itemPriceMap = new HashMap<>(); + itemPriceMap.put("Wrangler Jeans", 150.0); + itemPriceMap.put("Lee Jeans", 180.0); + + + Order order = new Order(); + order.setItemPriceMap(itemPriceMap); + + session.persist(order); + session.getTransaction().commit(); + + assertInsertedData(); + } + + private void assertInsertedData() { + @SuppressWarnings("unchecked") + List orderList = session.createQuery("FROM Order").list(); + + assertNotNull(orderList); + assertEquals(1, orderList.size()); + + Order order = orderList.get(0); + + Map itemPriceMap = order.getItemPriceMap(); + assertNotNull(itemPriceMap); + assertEquals(itemPriceMap.size(), 2); + assertEquals((Double) 150.0, itemPriceMap.get("Wrangler Jeans")); + assertEquals((Double) 180.0, itemPriceMap.get("Lee Jeans")); + + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java new file mode 100644 index 0000000000..221aa7b1d7 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java @@ -0,0 +1,95 @@ +package com.baeldung.hibernate.persistmaps; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkey.Item; +import com.baeldung.hibernate.persistmaps.mapkeyenumerated.Order; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MapKeyEnumeratedIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_ENUMERATED_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenData_whenInsertUsingMapKeyEnumerated_thenPersistMap() { + Item item1 = new Item(); + item1.setItemName("Wrangler Jeans"); + item1.setItemPrice(150.0); + item1.setItemType(ItemType.JEANS); + item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573))); + + + Item item2 = new Item(); + item2.setItemName("Armani Tshirts"); + item2.setItemPrice(180.0); + item2.setItemType(ItemType.TSHIRTS); + item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573))); + + Map itemMap = new HashMap<>(); + itemMap.put(item1.getItemType(), item1); + itemMap.put(item2.getItemType(), item2); + + Order order = new Order(); + order.setItemMap(itemMap); + + session.persist(order); + session.getTransaction().commit(); + + assertInsertedData(item1, item2); + } + + private void assertInsertedData(Item expectedItem1, Item expectedItem2) { + @SuppressWarnings("unchecked") + List orderList = session.createQuery("FROM Order").list(); + + assertNotNull(orderList); + assertEquals(1, orderList.size()); + + Order order = orderList.get(0); + + Map itemMap = order.getItemMap(); + assertNotNull(itemMap); + assertEquals(2, itemMap.size()); + assertEquals(expectedItem1, itemMap.get(ItemType.JEANS)); + assertEquals(expectedItem2, itemMap.get(ItemType.TSHIRTS)); + + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} + diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java new file mode 100644 index 0000000000..b500deb78e --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java @@ -0,0 +1,95 @@ +package com.baeldung.hibernate.persistmaps; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkey.Item; +import com.baeldung.hibernate.persistmaps.mapkey.Order; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MapKeyIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenData_whenInsertUsingMapKey_thenPersistMap() { + Item item1 = new Item(); + item1.setItemName("Wrangler Jeans"); + item1.setItemPrice(150.0); + item1.setItemType(ItemType.JEANS); + item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573))); + + + Item item2 = new Item(); + item2.setItemName("Armani Tshirts"); + item2.setItemPrice(180.0); + item2.setItemType(ItemType.TSHIRTS); + item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573))); + + Map itemMap = new HashMap<>(); + itemMap.put(item1.getItemName(), item1); + itemMap.put(item2.getItemName(), item2); + + Order order = new Order(); + order.setItemMap(itemMap); + + session.persist(order); + session.getTransaction().commit(); + + assertInsertedData(item1, item2); + } + + private void assertInsertedData(Item expectedItem1, Item expectedItem2) { + @SuppressWarnings("unchecked") + List orderList = session.createQuery("FROM Order").list(); + + assertNotNull(orderList); + assertEquals(1, orderList.size()); + + Order order = orderList.get(0); + + Map itemMap = order.getItemMap(); + assertNotNull(itemMap); + assertEquals(2, itemMap.size()); + assertEquals(expectedItem1, itemMap.get("Wrangler Jeans")); + assertEquals(expectedItem2, itemMap.get("Armani Tshirts")); + + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} + diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java new file mode 100644 index 0000000000..88b22f5c99 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java @@ -0,0 +1,105 @@ +package com.baeldung.hibernate.persistmaps; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Item; +import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Order; +import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Seller; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MapKeyJoinColumnIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_JOIN_COLUMN_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenData_whenInsertUsingMapKeyJoinColumn_thenPersistMap() { + Seller seller1 = new Seller(); + seller1.setSellerName("Walmart"); + + Item item1 = new Item(); + item1.setItemName("Wrangler Jeans"); + item1.setItemPrice(150.0); + item1.setItemType(ItemType.JEANS); + item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573))); + item1.setSeller(seller1); + + + Seller seller2 = new Seller(); + seller2.setSellerName("Amazon"); + + Item item2 = new Item(); + item2.setItemName("Armani Tshirts"); + item2.setItemPrice(180.0); + item2.setItemType(ItemType.TSHIRTS); + item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573))); + item2.setSeller(seller2); + + Map itemSellerMap = new HashMap<>(); + itemSellerMap.put(seller1, item1); + itemSellerMap.put(seller2, item2); + + Order order = new Order(); + order.setSellerItemMap(itemSellerMap); + + + session.persist(order); + session.getTransaction().commit(); + + assertInsertedData(seller1, item1, seller2, item2); + } + + private void assertInsertedData(Seller seller1, Item expectedItem1, Seller seller2, Item expectedItem2) { + @SuppressWarnings("unchecked") + List orderList = session.createQuery("FROM Order").list(); + + assertNotNull(orderList); + assertEquals(1, orderList.size()); + + Order order = orderList.get(0); + + Map sellerItemMap = order.getSellerItemMap(); + assertNotNull(sellerItemMap); + assertEquals(2, sellerItemMap.size()); + assertEquals(expectedItem1, sellerItemMap.get(seller1)); + assertEquals(expectedItem2, sellerItemMap.get(seller2)); + + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} + diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java new file mode 100644 index 0000000000..7117cad22f --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java @@ -0,0 +1,96 @@ +package com.baeldung.hibernate.persistmaps; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkey.Item; +import com.baeldung.hibernate.persistmaps.mapkeytemporal.Order; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MapKeyTemporalIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_TEMPORAL_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenData_whenInsertUsingMapKeyEnumerated_thenPersistMap() { + Date item1CreatedOn = Date.from(Instant.ofEpochSecond(1554926573)); + Item item1 = new Item(); + item1.setItemName("Wrangler Jeans"); + item1.setItemPrice(150.0); + item1.setItemType(ItemType.JEANS); + item1.setCreatedOn(item1CreatedOn); + + + Date item2CreatedOn = Date.from(Instant.ofEpochSecond(1554890573)); + Item item2 = new Item(); + item2.setItemName("Armani Tshirts"); + item2.setItemPrice(180.0); + item2.setItemType(ItemType.TSHIRTS); + item2.setCreatedOn(item2CreatedOn); + + Map itemMap = new HashMap<>(); + itemMap.put(item1CreatedOn, item1); + itemMap.put(item2CreatedOn, item2); + + Order order = new Order(); + order.setItemMap(itemMap); + + session.persist(order); + session.getTransaction().commit(); + + assertInsertedData(item1CreatedOn, item1, item2CreatedOn, item2); + } + + private void assertInsertedData(Date item1CreatedOn, Item expectedItem1, Date item2CreatedOn, Item expectedItem2) { + @SuppressWarnings("unchecked") + List orderList = session.createQuery("FROM Order").list(); + + assertNotNull(orderList); + assertEquals(1, orderList.size()); + + Order order = orderList.get(0); + + Map itemMap = order.getItemMap(); + assertNotNull(itemMap); + assertEquals(2, itemMap.size()); + assertEquals(expectedItem1, itemMap.get(item1CreatedOn)); + assertEquals(expectedItem2, itemMap.get(item2CreatedOn)); + + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserAdditionalValidationUnitTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserAdditionalValidationUnitTest.java new file mode 100644 index 0000000000..0f2a0403e9 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserAdditionalValidationUnitTest.java @@ -0,0 +1,290 @@ +package com.baeldung.hibernate.validation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; +import java.time.Duration; +import java.util.Set; + +import javax.money.CurrencyContextBuilder; +import javax.money.Monetary; +import javax.money.MonetaryAmount; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.constraints.CodePointLength; +import org.hibernate.validator.constraints.CreditCardNumber; +import org.hibernate.validator.constraints.Currency; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.LuhnCheck; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.SafeHtml; +import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.constraints.URL; +import org.hibernate.validator.constraints.time.DurationMax; +import org.hibernate.validator.constraints.time.DurationMin; +import org.javamoney.moneta.CurrencyUnitBuilder; +import org.javamoney.moneta.Money; +import org.junit.BeforeClass; +import org.junit.Test; + +public class UserAdditionalValidationUnitTest { + + private static Validator validator; + private Set> constraintViolations; + + @BeforeClass + public static void before() { + ValidatorFactory config = Validation.buildDefaultValidatorFactory(); + validator = config.getValidator(); + } + + @Test + public void whenValidationWithCCNAndNullCCN_thenNoConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + constraintViolations = validator.validateProperty(validations, "creditCardNumber"); + assertTrue(constraintViolations.isEmpty()); + } + + @Test + public void whenValidationWithCCNAndValidCCN_thenNoConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + validations.setCreditCardNumber("79927398713"); + constraintViolations = validator.validateProperty(validations, "creditCardNumber"); + assertTrue(constraintViolations.isEmpty()); + } + + @Test + public void whenValidationWithCCNAndInvalidCCN_thenConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + validations.setCreditCardNumber("79927398714"); + constraintViolations = validator.validateProperty(validations, "creditCardNumber"); + assertEquals(constraintViolations.size(), 2); + } + + @Test + public void whenValidationWithCCNAndValidCCNWithDashes_thenConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + validations.setCreditCardNumber("7992-7398-713"); + constraintViolations = validator.validateProperty(validations, "creditCardNumber"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenValidationWithLenientCCNAndValidCCNWithDashes_thenNoConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + validations.setLenientCreditCardNumber("7992-7398-713"); + constraintViolations = validator.validateProperty(validations, "lenientCreditCardNumber"); + assertTrue(constraintViolations.isEmpty()); + } + + @Test + public void whenMonetaryAmountWithRightCurrency_thenNoConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setBalance(Money.of(new BigDecimal(100.0), Monetary.getCurrency("EUR"))); + constraintViolations = validator.validateProperty(bean, "balance"); + assertEquals(0, constraintViolations.size()); + } + + @Test + public void whenMonetaryAmountWithWrongCurrency_thenConstraintViolation() { + AdditionalValidations validations = new AdditionalValidations(); + validations.setBalance(Money.of(new BigDecimal(100.0), Monetary.getCurrency("USD"))); + constraintViolations = validator.validateProperty(validations, "balance"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenDurationShorterThanMin_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setDuration(Duration.ofDays(1).plusHours(1)); + constraintViolations = validator.validateProperty(bean, "duration"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenDurationLongerThanMax_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setDuration(Duration.ofDays(2).plusHours(3)); + constraintViolations = validator.validateProperty(bean, "duration"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenDurationBetweenMinAndMax_thenNoConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setDuration(Duration.ofDays(2)); + constraintViolations = validator.validateProperty(bean, "duration"); + assertEquals(0, constraintViolations.size()); + } + + @Test + public void whenValueBelowRangeMin_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setPercent(new BigDecimal("-1.4")); + constraintViolations = validator.validateProperty(bean, "percent"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenValueAboveRangeMax_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setPercent(new BigDecimal("100.03")); + constraintViolations = validator.validateProperty(bean, "percent"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenValueInRange_thenNoConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setPercent(new BigDecimal("53.23")); + constraintViolations = validator.validateProperty(bean, "percent"); + assertEquals(0, constraintViolations.size()); + } + + @Test + public void whenLengthInRange_thenNoConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setSomeString("aaa"); + constraintViolations = validator.validateProperty(bean, "someString"); + assertEquals(0, constraintViolations.size()); + } + + @Test + public void whenCodePointLengthNotInRange_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + bean.setSomeString("aa\uD835\uDD0A"); + constraintViolations = validator.validateProperty(bean, "someString"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenValidUrlWithWrongProtocol_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + + bean.setUrl("https://www.google.com/"); + constraintViolations = validator.validateProperty(bean, "url"); + assertEquals(0, constraintViolations.size()); + + bean.setUrl("http://www.google.com/"); + constraintViolations = validator.validateProperty(bean, "url"); + assertEquals(1, constraintViolations.size()); + + bean.setUrl("https://foo:bar"); + constraintViolations = validator.validateProperty(bean, "url"); + assertEquals(1, constraintViolations.size()); + } + + @Test + public void whenScriptAssertFails_thenConstraintViolation() { + AdditionalValidations bean = new AdditionalValidations(); + + constraintViolations = validator.validate(bean); + assertEquals(0, constraintViolations.size()); + + bean.setValid(false); + + constraintViolations = validator.validate(bean); + assertEquals(1, constraintViolations.size()); + + constraintViolations = validator.validateProperty(bean, "valid"); + assertEquals(0, constraintViolations.size()); + } + + @ScriptAssert(lang = "nashorn", script = "_this.valid") + public class AdditionalValidations { + private boolean valid = true; + + @CreditCardNumber + @LuhnCheck(startIndex = 0, endIndex = Integer.MAX_VALUE, checkDigitIndex = -1) + private String creditCardNumber; + + @CreditCardNumber(ignoreNonDigitCharacters = true) + private String lenientCreditCardNumber; + + @Currency("EUR") + private MonetaryAmount balance; + + @DurationMin(days = 1, hours = 2) + @DurationMax(days = 2, hours = 1) + private Duration duration; + + @Range(min = 0, max = 100) + private BigDecimal percent; + + @Length(min = 1, max = 3) + @CodePointLength(min = 1, max = 3) + private String someString; + + @URL(protocol = "https") + private String url; + + public String getCreditCardNumber() { + return creditCardNumber; + } + + public void setCreditCardNumber(String creditCardNumber) { + this.creditCardNumber = creditCardNumber; + } + + public String getLenientCreditCardNumber() { + return lenientCreditCardNumber; + } + + public void setLenientCreditCardNumber(String lenientCreditCardNumber) { + this.lenientCreditCardNumber = lenientCreditCardNumber; + } + + public MonetaryAmount getBalance() { + return balance; + } + + public void setBalance(MonetaryAmount balance) { + this.balance = balance; + } + + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; + } + + public BigDecimal getPercent() { + return percent; + } + + public void setPercent(BigDecimal percent) { + this.percent = percent; + } + + public String getSomeString() { + return someString; + } + + public void setSomeString(String someString) { + this.someString = someString; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean valid) { + this.valid = valid; + } + + } +} diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserValidationUnitTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserValidationUnitTest.java new file mode 100644 index 0000000000..e39f324856 --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/validation/UserValidationUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.hibernate.validation; + +import static org.junit.Assert.assertEquals; +import java.util.Set; +import javax.persistence.PersistenceException; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.Strategy; +import com.baeldung.hibernate.persistmaps.mapkey.User; + +public class UserValidationUnitTest { + + private static Validator validator; + private static SessionFactory sessionFactory; + private Session session; + private Set> constraintViolations; + + @BeforeClass + public static void before() { + ValidatorFactory config = Validation.buildDefaultValidatorFactory(); + validator = config.getValidator(); + sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_BASED); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void whenValidationWithSizeAndInvalidMiddleName_thenConstraintViolation() { + User user = new User("john", "m", "butler", "japan"); + constraintViolations = validator.validateProperty(user, "middleName"); + assertEquals(constraintViolations.size(), 1); + } + + @Test + public void whenValidationWithSizeAndValidMiddleName_thenNoConstraintViolation() { + User user = new User("john", "mathis", "butler", "japan"); + constraintViolations = validator.validateProperty(user, "middleName"); + assertEquals(constraintViolations.size(), 0); + } + + @Test + public void whenValidationWithLengthAndInvalidLastName_thenConstraintViolation() { + User user = new User("john", "m", "b", "japan"); + constraintViolations = validator.validateProperty(user, "lastName"); + assertEquals(constraintViolations.size(), 1); + } + + @Test + public void whenValidationWithLengthAndValidLastName_thenNoConstraintViolation() { + User user = new User("john", "mathis", "butler", "japan"); + constraintViolations = validator.validateProperty(user, "lastName"); + assertEquals(constraintViolations.size(), 0); + } + + @Test(expected = PersistenceException.class) + public void whenSavingFirstNameWithInvalidFirstName_thenPersistenceException() { + User user = new User("john", "mathis", "butler", "japan"); + session.save(user); + session.getTransaction() + .commit(); + } + + @Test + public void whenValidationWithSizeAndColumnWithValidCity_thenNoConstraintViolation() { + User user = new User("john", "mathis", "butler", "japan"); + constraintViolations = validator.validateProperty(user, "city"); + assertEquals(constraintViolations.size(), 0); + } +} diff --git a/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties b/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties new file mode 100644 index 0000000000..c22da2496b --- /dev/null +++ b/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties @@ -0,0 +1,10 @@ +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop + diff --git a/persistence-modules/hibernate-ogm/README.md b/persistence-modules/hibernate-ogm/README.md index f4a5bb6c3b..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](http://www.baeldung.com/xxxx) +- [A Guide to Hibernate OGM](https://www.baeldung.com/hibernate-ogm) diff --git a/persistence-modules/hibernate-ogm/pom.xml b/persistence-modules/hibernate-ogm/pom.xml index 2ccac03bd3..7ac29b1720 100644 --- a/persistence-modules/hibernate-ogm/pom.xml +++ b/persistence-modules/hibernate-ogm/pom.xml @@ -19,31 +19,31 @@ org.hibernate.ogm hibernate-ogm-mongodb - 5.4.0.Final + ${hibernate.version} org.hibernate.ogm hibernate-ogm-neo4j - 5.4.0.Final + ${hibernate.version} org.jboss.narayana.jta narayana-jta - 5.5.23.Final + ${narayana-jta.version} junit junit - 4.12 + ${junit.version} test org.easytesting fest-assert - 1.4 + ${fest-assert.version} test @@ -57,4 +57,10 @@ + + + 5.4.0.Final + 1.4 + 5.5.23.Final + \ No newline at end of file diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index b6e112b5fc..65322f0cea 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -18,6 +18,19 @@ - [@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) +- [Criteria Queries Using JPA Metamodel](https://www.baeldung.com/hibernate-criteria-queries-metamodel) +- [Guide to the Hibernate EntityManager](https://www.baeldung.com/hibernate-entitymanager) +- [Get All Data from a Table with Hibernate](https://www.baeldung.com/hibernate-select-all) +- [One-to-One Relationship in JPA](https://www.baeldung.com/jpa-one-to-one) +- [Hibernate Named Query](https://www.baeldung.com/hibernate-named-query) +- [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) +- [Hibernate Query Plan Cache](https://www.baeldung.com/hibernate-query-plan-cache) +- [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) +- [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index f5a3a7e4c9..bf4b2d27ec 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -1,11 +1,12 @@ - + 4.0.0 com.baeldung hibernate5 0.0.1-SNAPSHOT - hibernate5 + hibernate5 com.baeldung @@ -29,13 +30,18 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.hibernate hibernate-spatial ${hibernate.version} + + org.opengeo + geodb + ${geodb.version} + org.hibernate hibernate-c3p0 @@ -54,7 +60,7 @@ org.hibernate hibernate-testing - 5.2.2.Final + ${hibernate.version} com.fasterxml.jackson.core @@ -64,7 +70,28 @@ net.bytebuddy byte-buddy - 1.9.5 + ${byte-buddy.version} + + + + org.hibernate + hibernate-jpamodelgen + ${hibernate.version} + + + org.openjdk.jmh + jmh-core + ${openjdk-jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${openjdk-jmh.version} + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} @@ -72,19 +99,29 @@ hibernate5 - src/main/resources + src/test/resources true + + + + geodb-repo + GeoDB repository + http://repo.boundlessgeo.com/main/ + + - 5.3.6.Final + 5.3.7.Final 6.0.6 2.2.3 - 1.4.196 3.8.0 - 2.8.11.3 + 1.21 + 0.9 + 1.9.5 + 2.3.0 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 e0d1de591b..137fc4f0bd 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 @@ -5,27 +5,25 @@ import java.io.IOException; import java.net.URL; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + import com.baeldung.hibernate.customtypes.LocalDateStringType; import com.baeldung.hibernate.customtypes.OfficeEmployee; import com.baeldung.hibernate.entities.DeptEmployee; +import com.baeldung.hibernate.joincolumn.Email; +import com.baeldung.hibernate.joincolumn.Office; +import com.baeldung.hibernate.joincolumn.OfficeAddress; import com.baeldung.hibernate.optimisticlocking.OptimisticLockingCourse; import com.baeldung.hibernate.optimisticlocking.OptimisticLockingStudent; import com.baeldung.hibernate.pessimisticlocking.Individual; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingCourse; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingEmployee; import com.baeldung.hibernate.pessimisticlocking.PessimisticLockingStudent; -import com.baeldung.hibernate.pojo.*; -import com.baeldung.hibernate.pojo.Person; -import com.baeldung.hibernate.pojo.inheritance.*; -import org.apache.commons.lang3.StringUtils; -import org.hibernate.SessionFactory; -import org.hibernate.boot.Metadata; -import org.hibernate.boot.MetadataBuilder; -import org.hibernate.boot.MetadataSources; -import org.hibernate.boot.registry.StandardServiceRegistryBuilder; -import org.hibernate.cfg.Configuration; -import org.hibernate.service.ServiceRegistry; - import com.baeldung.hibernate.pojo.Course; import com.baeldung.hibernate.pojo.Employee; import com.baeldung.hibernate.pojo.EntityDescription; @@ -36,6 +34,7 @@ import com.baeldung.hibernate.pojo.Person; import com.baeldung.hibernate.pojo.Phone; import com.baeldung.hibernate.pojo.PointEntity; import com.baeldung.hibernate.pojo.PolygonEntity; +import com.baeldung.hibernate.pojo.Post; import com.baeldung.hibernate.pojo.Product; import com.baeldung.hibernate.pojo.Student; import com.baeldung.hibernate.pojo.TemporalValues; @@ -52,7 +51,6 @@ import com.baeldung.hibernate.pojo.inheritance.Pet; import com.baeldung.hibernate.pojo.inheritance.Vehicle; public class HibernateUtil { - private static SessionFactory sessionFactory; private static String PROPERTY_FILE_NAME; public static SessionFactory getSessionFactory() throws IOException { @@ -61,11 +59,13 @@ public class HibernateUtil { public static SessionFactory getSessionFactory(String propertyFileName) throws IOException { PROPERTY_FILE_NAME = propertyFileName; - if (sessionFactory == null) { - ServiceRegistry serviceRegistry = configureServiceRegistry(); - sessionFactory = makeSessionFactory(serviceRegistry); - } - return sessionFactory; + ServiceRegistry serviceRegistry = configureServiceRegistry(); + return makeSessionFactory(serviceRegistry); + } + + public static SessionFactory getSessionFactoryByProperties(Properties properties) throws IOException { + ServiceRegistry serviceRegistry = configureServiceRegistry(properties); + return makeSessionFactory(serviceRegistry); } private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) { @@ -108,6 +108,11 @@ public class HibernateUtil { metadataSources.addAnnotatedClass(OptimisticLockingCourse.class); metadataSources.addAnnotatedClass(OptimisticLockingStudent.class); metadataSources.addAnnotatedClass(OfficeEmployee.class); + metadataSources.addAnnotatedClass(Post.class); + metadataSources.addAnnotatedClass(com.baeldung.hibernate.joincolumn.OfficialEmployee.class); + metadataSources.addAnnotatedClass(Email.class); + metadataSources.addAnnotatedClass(Office.class); + metadataSources.addAnnotatedClass(OfficeAddress.class); Metadata metadata = metadataSources.getMetadataBuilder() .applyBasicType(LocalDateStringType.INSTANCE) @@ -119,12 +124,15 @@ public class HibernateUtil { } private static ServiceRegistry configureServiceRegistry() throws IOException { - Properties properties = getProperties(); + return configureServiceRegistry(getProperties()); + } + + private static ServiceRegistry configureServiceRegistry(Properties properties) throws IOException { return new StandardServiceRegistryBuilder().applySettings(properties) .build(); } - private static Properties getProperties() throws IOException { + public static Properties getProperties() throws IOException { Properties properties = new Properties(); URL propertiesURL = Thread.currentThread() .getContextClassLoader() diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java new file mode 100644 index 0000000000..35cfe55ba6 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java @@ -0,0 +1,60 @@ +package com.baeldung.hibernate.criteriaquery; + +import com.baeldung.hibernate.customtypes.LocalDateStringType; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + + private HibernateUtil() { + } + + public static SessionFactory getSessionFactory() { + if (sessionFactory == null) { + sessionFactory = buildSessionFactory(); + } + return sessionFactory; + } + + private static SessionFactory buildSessionFactory() { + try { + ServiceRegistry serviceRegistry = configureServiceRegistry(); + + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + + metadataSources.addAnnotatedClass(Student.class); + Metadata metadata = metadataSources.getMetadataBuilder() + .applyBasicType(LocalDateStringType.INSTANCE) + .build(); + return metadata.getSessionFactoryBuilder().build(); + } catch (IOException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + + private static ServiceRegistry configureServiceRegistry() throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties).build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource("hibernate.properties"); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/Student.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/Student.java new file mode 100644 index 0000000000..314e7ca557 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/Student.java @@ -0,0 +1,58 @@ +package com.baeldung.hibernate.criteriaquery; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "students") +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @Column(name = "first_name") + private String firstName; + + @Column(name = "last_name") + private String lastName; + + @Column(name = "grad_year") + private int gradYear; + + public int getId() { + return id; + } + + public void setId(int 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; + } + + public int getGradYear() { + return gradYear; + } + + public void setGradYear(int gradYear) { + this.gradYear = gradYear; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java new file mode 100644 index 0000000000..989fa1281a --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java @@ -0,0 +1,16 @@ +package com.baeldung.hibernate.exception; + +import javax.persistence.Entity; + +@Entity +public class EntityWithNoId { + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java new file mode 100644 index 0000000000..ae5174ac9c --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java @@ -0,0 +1,63 @@ +package com.baeldung.hibernate.exception; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +import org.apache.commons.lang3.StringUtils; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + private static String PROPERTY_FILE_NAME; + + public static SessionFactory getSessionFactory() throws IOException { + return getSessionFactory(null); + } + + public static SessionFactory getSessionFactory(String propertyFileName) + throws IOException { + PROPERTY_FILE_NAME = propertyFileName; + if (sessionFactory == null) { + ServiceRegistry serviceRegistry = configureServiceRegistry(); + sessionFactory = makeSessionFactory(serviceRegistry); + } + return sessionFactory; + } + + private static SessionFactory makeSessionFactory( + ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(Product.class); + Metadata metadata = metadataSources.getMetadataBuilder() + .build(); + return metadata.getSessionFactoryBuilder() + .build(); + + } + + private static ServiceRegistry configureServiceRegistry() + throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, + "hibernate-exception.properties")); + try (FileInputStream inputStream = new FileInputStream( + propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java new file mode 100644 index 0000000000..031fa38de0 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java @@ -0,0 +1,40 @@ +package com.baeldung.hibernate.exception; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Product { + + private int id; + + private String name; + private String description; + + @Id + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Column(nullable=false) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Email.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Email.java index a91fb3b4c9..df07c3cf69 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Email.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Email.java @@ -19,7 +19,7 @@ public class Email { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "employee_id") - private Employee employee; + private OfficialEmployee employee; public Long getId() { return id; @@ -37,11 +37,11 @@ public class Email { this.address = address; } - public Employee getEmployee() { + public OfficialEmployee getEmployee() { return employee; } - public void setEmployee(Employee employee) { + public void setEmployee(OfficialEmployee employee) { this.employee = employee; } } \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Office.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Office.java index e5b9dc06bc..9940577761 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Office.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Office.java @@ -21,7 +21,7 @@ public class Office { @JoinColumn(name="ADDR_ID", referencedColumnName="ID"), @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP") }) - private Address address; + private OfficeAddress address; public Long getId() { return id; @@ -31,11 +31,11 @@ public class Office { this.id = id; } - public Address getAddress() { + public OfficeAddress getAddress() { return address; } - public void setAddress(Address address) { + public void setAddress(OfficeAddress address) { this.address = address; } } \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Address.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficeAddress.java similarity index 95% rename from persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Address.java rename to persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficeAddress.java index 8b0a51858d..cc723db6a2 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Address.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficeAddress.java @@ -7,7 +7,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; @Entity -public class Address { +public class OfficeAddress { @Id @GeneratedValue(strategy = GenerationType.AUTO) diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Employee.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficialEmployee.java similarity index 95% rename from persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Employee.java rename to persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficialEmployee.java index 3fbdb3820e..49c63c7578 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/Employee.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/joincolumn/OfficialEmployee.java @@ -9,7 +9,7 @@ import javax.persistence.Id; import javax.persistence.OneToMany; @Entity -public class Employee { +public class OfficialEmployee { @Id @GeneratedValue(strategy = GenerationType.AUTO) diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/onetoone/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/onetoone/HibernateUtil.java index 972ade9671..c2f276472e 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/onetoone/HibernateUtil.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/onetoone/HibernateUtil.java @@ -19,10 +19,7 @@ public class HibernateUtil { } public static SessionFactory getSessionFactory(Strategy strategy) { - if (sessionFactory == null) { - sessionFactory = buildSessionFactory(strategy); - } - return sessionFactory; + return buildSessionFactory(strategy); } private static SessionFactory buildSessionFactory(Strategy strategy) { diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Course.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Course.java index 97760acd3b..2214b9a56f 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Course.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Course.java @@ -20,8 +20,8 @@ public class Course { public void setCourseId(UUID courseId) { this.courseId = courseId; } - - - + + + } diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/PointEntity.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/PointEntity.java index 223f5dcbde..736abde866 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/PointEntity.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/PointEntity.java @@ -2,6 +2,7 @@ package com.baeldung.hibernate.pojo; import com.vividsolutions.jts.geom.Point; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -13,6 +14,7 @@ public class PointEntity { @GeneratedValue private Long id; + @Column(columnDefinition="BINARY(2048)") private Point point; public PointEntity() { 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/pojo/Student.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java index a6dec4a30d..9b26c117eb 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Student.java @@ -9,15 +9,43 @@ import javax.persistence.Id; public class Student { @Id - @GeneratedValue (strategy = GenerationType.SEQUENCE) + @GeneratedValue(strategy = GenerationType.SEQUENCE) private long studentId; + private String name; + + private int age; + + public Student() { + } + + public Student(String name, int age) { + this.name = name; + this.age = age; + } + public long getStudentId() { return studentId; } - public void setStudent_id(long studentId) { + public void setStudentId(long studentId) { this.studentId = studentId; } - + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } 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/DynamicMappingIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/DynamicMappingIntegrationTest.java index b207d6630a..7a112200b5 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/DynamicMappingIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/DynamicMappingIntegrationTest.java @@ -122,11 +122,7 @@ public class DynamicMappingIntegrationTest { Employee employee = session.get(Employee.class, 1); assertThat(employee.getGrossIncome()).isEqualTo(10_000); - session.close(); - - session = HibernateUtil.getSessionFactory().openSession(); - transaction = session.beginTransaction(); - + session.disableFilter("incomeLevelFilter"); employees = session.createQuery("from Employee").getResultList(); assertThat(employees).hasSize(3); diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/HibernateSpatialIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/HibernateSpatialIntegrationTest.java index 975490aa7c..74f752ab8c 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/HibernateSpatialIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/HibernateSpatialIntegrationTest.java @@ -4,7 +4,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.io.FileInputStream; import java.io.IOException; +import java.net.URL; +import java.util.Properties; import javax.persistence.Query; @@ -24,6 +27,8 @@ import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; import com.vividsolutions.jts.util.GeometricShapeFactory; +import geodb.GeoDB; + public class HibernateSpatialIntegrationTest { private Session session; @@ -34,6 +39,7 @@ public class HibernateSpatialIntegrationTest { session = HibernateUtil.getSessionFactory("hibernate-spatial.properties") .openSession(); transaction = session.beginTransaction(); + session.doWork(conn -> { GeoDB.InitGeoDB(conn); }); } @After @@ -141,4 +147,15 @@ public class HibernateSpatialIntegrationTest { shapeFactory.setSize(radius * 2); return shapeFactory.createCircle(); } + + public static Properties getProperties(String propertyFile) throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(propertyFile); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java new file mode 100644 index 0000000000..0b2bdf7ead --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/aggregatefunctions/AggregateFunctionsIntegrationTest.java @@ -0,0 +1,87 @@ +package com.baeldung.hibernate.aggregatefunctions; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.pojo.Student; + +public class AggregateFunctionsIntegrationTest { + + private static Session session; + private static Transaction transaction; + + @BeforeClass + public static final void setup() throws HibernateException, IOException { + session = HibernateUtil.getSessionFactory() + .openSession(); + transaction = session.beginTransaction(); + + Student jonas = new Student("Jonas", 22); + session.save(jonas); + + Student sally = new Student("Sally", 20); + session.save(sally); + + Student simon = new Student("Simon", 25); + session.save(simon); + + Student raven = new Student("Raven", 21); + session.save(raven); + + Student sam = new Student("Sam", 23); + session.save(sam); + + } + + @AfterClass + public static final void teardown() { + if (session != null) { + transaction.rollback(); + session.close(); + } + } + + @Test + public void whenMaxAge_ThenReturnValue() { + int maxAge = (int) session.createQuery("SELECT MAX(age) from Student") + .getSingleResult(); + assertThat(maxAge).isEqualTo(25); + } + + @Test + public void whenMinAge_ThenReturnValue() { + int minAge = (int) session.createQuery("SELECT MIN(age) from Student") + .getSingleResult(); + assertThat(minAge).isEqualTo(20); + } + + @Test + public void whenAverageAge_ThenReturnValue() { + Double avgAge = (Double) session.createQuery("SELECT AVG(age) from Student") + .getSingleResult(); + assertThat(avgAge).isEqualTo(22.2); + } + + @Test + public void whenCountAll_ThenReturnValue() { + Long totalStudents = (Long) session.createQuery("SELECT COUNT(*) from Student") + .getSingleResult(); + assertThat(totalStudents).isEqualTo(5); + } + + @Test + public void whenSumOfAllAges_ThenReturnValue() { + Long sumOfAllAges = (Long) session.createQuery("SELECT SUM(age) from Student") + .getSingleResult(); + assertThat(sumOfAllAges).isEqualTo(111); + } +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/bootstrap/BootstrapAPIIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/bootstrap/BootstrapAPIIntegrationTest.java new file mode 100644 index 0000000000..19988b45be --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/bootstrap/BootstrapAPIIntegrationTest.java @@ -0,0 +1,47 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.pojo.Movie; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; +import org.junit.After; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertNotNull; + +public class BootstrapAPIIntegrationTest { + + SessionFactory sessionFactory = null; + + @Test + public void whenServiceRegistryAndMetadata_thenSessionFactory() throws IOException { + + BootstrapServiceRegistry bootstrapRegistry = new BootstrapServiceRegistryBuilder() + .build(); + + ServiceRegistry standardRegistry = new StandardServiceRegistryBuilder(bootstrapRegistry) + // No need for hibernate.cfg.xml file, an hibernate.properties is sufficient. + //.configure() + .build(); + + MetadataSources metadataSources = new MetadataSources(standardRegistry); + metadataSources.addAnnotatedClass(Movie.class); + + Metadata metadata = metadataSources.getMetadataBuilder().build(); + + sessionFactory = metadata.buildSessionFactory(); + assertNotNull(sessionFactory); + sessionFactory.close(); + } + + @After + public void clean() throws IOException { + sessionFactory.close(); + } +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/criteriaquery/TypeSafeCriteriaIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/criteriaquery/TypeSafeCriteriaIntegrationTest.java new file mode 100644 index 0000000000..cedba412d9 --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/criteriaquery/TypeSafeCriteriaIntegrationTest.java @@ -0,0 +1,89 @@ +package com.baeldung.hibernate.criteriaquery; + +import com.baeldung.hibernate.criteriaquery.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.query.Query; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + + +public class TypeSafeCriteriaIntegrationTest { + + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() throws IOException { + sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenStudentData_whenUsingTypeSafeCriteriaQuery_thenSearchAllStudentsOfAGradYear() { + + prepareData(); + CriteriaBuilder cb = session.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = cb.createQuery(Student.class); + + Root root = criteriaQuery.from(Student.class); + criteriaQuery.select(root).where(cb.equal(root.get("gradYear"), 1965)); + + Query query = session.createQuery(criteriaQuery); + List results = query.getResultList(); + + assertNotNull(results); + assertEquals(1, results.size()); + + Student student = results.get(0); + + assertEquals("Ken", student.getFirstName()); + assertEquals("Thompson", student.getLastName()); + assertEquals(1965, student.getGradYear()); + } + + private void prepareData() { + Student student1 = new Student(); + student1.setFirstName("Ken"); + student1.setLastName("Thompson"); + student1.setGradYear(1965); + + session.save(student1); + + Student student2 = new Student(); + student2.setFirstName("Dennis"); + student2.setLastName("Ritchie"); + student2.setGradYear(1963); + + session.save(student2); + session.getTransaction().commit(); + } + + @After + public void tearDown() { + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java new file mode 100644 index 0000000000..3581c81daa --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java @@ -0,0 +1,425 @@ +package com.baeldung.hibernate.exception; + +import static org.hamcrest.CoreMatchers.isA; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.List; + +import javax.persistence.OptimisticLockException; +import javax.persistence.PersistenceException; + +import org.hibernate.AnnotationException; +import org.hibernate.HibernateException; +import org.hibernate.MappingException; +import org.hibernate.NonUniqueObjectException; +import org.hibernate.PropertyValueException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.StaleObjectStateException; +import org.hibernate.StaleStateException; +import org.hibernate.Transaction; +import org.hibernate.TransactionException; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.exception.ConstraintViolationException; +import org.hibernate.exception.DataException; +import org.hibernate.exception.SQLGrammarException; +import org.hibernate.query.NativeQuery; +import org.hibernate.tool.schema.spi.CommandAcceptanceException; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HibernateExceptionUnitTest { + + private static final Logger logger = LoggerFactory + .getLogger(HibernateExceptionUnitTest.class); + private SessionFactory sessionFactory; + + @Before + public void setUp() throws IOException { + sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Configuration getConfiguration() { + Configuration cfg = new Configuration(); + cfg.setProperty(AvailableSettings.DIALECT, + "org.hibernate.dialect.H2Dialect"); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); + cfg.setProperty(AvailableSettings.DRIVER, "org.h2.Driver"); + cfg.setProperty(AvailableSettings.URL, + "jdbc:h2:mem:myexceptiondb2;DB_CLOSE_DELAY=-1"); + cfg.setProperty(AvailableSettings.USER, "sa"); + cfg.setProperty(AvailableSettings.PASS, ""); + return cfg; + } + + @Test + public void whenQueryExecutedWithUnmappedEntity_thenMappingException() { + thrown.expectCause(isA(MappingException.class)); + thrown.expectMessage("Unknown entity: java.lang.String"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session + .createNativeQuery("select name from PRODUCT", String.class); + query.getResultList(); + } + + @Test + @SuppressWarnings("rawtypes") + public void whenQueryExecuted_thenOK() { + Session session = sessionFactory.openSession(); + NativeQuery query = session + .createNativeQuery("select name from PRODUCT"); + List results = query.getResultList(); + assertNotNull(results); + } + + @Test + public void givenEntityWithoutId_whenSessionFactoryCreated_thenAnnotationException() { + thrown.expect(AnnotationException.class); + thrown.expectMessage("No identifier specified for entity"); + + Configuration cfg = getConfiguration(); + cfg.addAnnotatedClass(EntityWithNoId.class); + cfg.buildSessionFactory(); + } + + @Test + public void givenMissingTable_whenSchemaValidated_thenSchemaManagementException() { + thrown.expect(SchemaManagementException.class); + thrown.expectMessage("Schema-validation: missing table"); + + Configuration cfg = getConfiguration(); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "validate"); + cfg.addAnnotatedClass(Product.class); + cfg.buildSessionFactory(); + } + + @Test + public void whenWrongDialectSpecified_thenCommandAcceptanceException() { + thrown.expect(SchemaManagementException.class); + thrown.expectCause(isA(CommandAcceptanceException.class)); + thrown.expectMessage("Halting on error : Error executing DDL"); + + Configuration cfg = getConfiguration(); + cfg.setProperty(AvailableSettings.DIALECT, + "org.hibernate.dialect.MySQLDialect"); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); + + // This does not work due to hibernate bug + // cfg.setProperty(AvailableSettings.HBM2DDL_HALT_ON_ERROR,"true"); + cfg.getProperties() + .put(AvailableSettings.HBM2DDL_HALT_ON_ERROR, true); + + cfg.addAnnotatedClass(Product.class); + cfg.buildSessionFactory(); + } + + @Test + public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(SQLGrammarException.class)); + thrown + .expectMessage("SQLGrammarException: could not prepare statement"); + + Configuration cfg = getConfiguration(); + cfg.addAnnotatedClass(Product.class); + + SessionFactory sessionFactory = cfg.buildSessionFactory(); + Session session = null; + Transaction transaction = null; + try { + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product = new Product(); + product.setId(1); + product.setName("Product 1"); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + closeSessionFactoryQuietly(sessionFactory); + } + } + + @Test + public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(SQLGrammarException.class)); + thrown + .expectMessage("SQLGrammarException: could not prepare statement"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session.createNativeQuery( + "select * from NON_EXISTING_TABLE", Product.class); + query.getResultList(); + } + + @Test + public void whenDuplicateIdSaved_thenConstraintViolationException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(ConstraintViolationException.class)); + thrown.expectMessage( + "ConstraintViolationException: could not execute statement"); + + Session session = null; + Transaction transaction = null; + + for (int i = 1; i <= 2; i++) { + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product = new Product(); + product.setId(1); + product.setName("Product " + i); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + } + + @Test + public void givenNotNullPropertyNotSet_whenEntityIdSaved_thenPropertyValueException() { + thrown.expect(isA(PropertyValueException.class)); + thrown.expectMessage( + "not-null property references a null or transient value"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product = new Product(); + product.setId(1); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + + } + + @Test + public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() { + thrown.expectCause(isA(DataException.class)); + thrown.expectMessage( + "org.hibernate.exception.DataException: could not prepare statement"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session.createNativeQuery( + "select * from PRODUCT where id='wrongTypeId'", Product.class); + query.getResultList(); + } + + @Test + public void givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException() { + thrown.expect(isA(NonUniqueObjectException.class)); + thrown.expectMessage( + "A different object with the same identifier value was already associated with the session"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(1); + product1.setName("Product 1"); + session.save(product1); + + Product product2 = new Product(); + product2.setId(1); + product2.setName("Product 2"); + session.save(product2); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void whenDeletingADeletedObject_thenOptimisticLockException() { + thrown.expect(isA(OptimisticLockException.class)); + thrown.expectMessage( + "Batch update returned unexpected row count from update"); + thrown.expectCause(isA(StaleStateException.class)); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(12); + product1.setName("Product 12"); + session.save(product1); + transaction.commit(); + session.close(); + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product2 = session.get(Product.class, 12); + session.createNativeQuery("delete from Product where id=12") + .executeUpdate(); + // We need to refresh to fix the error. + // session.refresh(product2); + session.delete(product2); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void whenUpdatingNonExistingObject_thenStaleStateException() { + thrown.expect(isA(OptimisticLockException.class)); + thrown + .expectMessage("Row was updated or deleted by another transaction"); + thrown.expectCause(isA(StaleObjectStateException.class)); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(15); + product1.setName("Product1"); + session.update(product1); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void givenTxnMarkedRollbackOnly_whenCommitted_thenTransactionException() { + thrown.expect(isA(TransactionException.class)); + + Session session = null; + Transaction transaction = null; + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(15); + product1.setName("Product1"); + session.save(product1); + transaction.setRollbackOnly(); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + private void rollbackTransactionQuietly(Transaction transaction) { + if (transaction != null && transaction.isActive()) { + try { + transaction.rollback(); + } catch (Exception e) { + logger.error("Exception while rolling back transaction", e); + } + } + } + + private void closeSessionQuietly(Session session) { + if (session != null) { + try { + session.close(); + } catch (Exception e) { + logger.error("Exception while closing session", e); + } + } + } + + private void closeSessionFactoryQuietly(SessionFactory sessionFactory) { + if (sessionFactory != null) { + try { + sessionFactory.close(); + } catch (Exception e) { + logger.error("Exception while closing sessionFactory", e); + } + } + } + + @Test + public void givenExistingEntity_whenIdUpdated_thenHibernateException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(HibernateException.class)); + thrown.expectMessage( + "identifier of an instance of com.baeldung.hibernate.exception.Product was altered"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(222); + product1.setName("Product 222"); + session.save(product1); + transaction.commit(); + closeSessionQuietly(session); + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product2 = session.get(Product.class, 222); + product2.setId(333); + session.save(product2); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/joincolumn/JoinColumnIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/joincolumn/JoinColumnIntegrationTest.java index 8246a2b01e..0998ff1d90 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/joincolumn/JoinColumnIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/joincolumn/JoinColumnIntegrationTest.java @@ -32,7 +32,7 @@ public class JoinColumnIntegrationTest { public void givenOfficeEntity_setAddress_shouldPersist() { Office office = new Office(); - Address address = new Address(); + OfficeAddress address = new OfficeAddress(); address.setZipCode("11-111"); office.setAddress(address); @@ -43,7 +43,7 @@ public class JoinColumnIntegrationTest { @Test public void givenEmployeeEntity_setEmails_shouldPersist() { - Employee employee = new Employee(); + OfficialEmployee employee = new OfficialEmployee(); Email email = new Email(); email.setAddress("example@email.com"); diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/optimisticlocking/OptimisticLockingIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/optimisticlocking/OptimisticLockingIntegrationTest.java index 68b51764e4..37c490f297 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/optimisticlocking/OptimisticLockingIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/optimisticlocking/OptimisticLockingIntegrationTest.java @@ -1,17 +1,23 @@ package com.baeldung.hibernate.optimisticlocking; -import com.baeldung.hibernate.HibernateUtil; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import java.io.IOException; +import java.util.Arrays; import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.OptimisticLockException; -import java.io.IOException; -import java.util.Arrays; + +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.hibernate.HibernateUtil; public class OptimisticLockingIntegrationTest { + + private static SessionFactory sessionFactory; @Before public void setUp() throws IOException { @@ -124,11 +130,17 @@ public class OptimisticLockingIntegrationTest { protected static EntityManager getEntityManagerWithOpenTransaction() throws IOException { String propertyFileName = "hibernate-pessimistic-locking.properties"; - EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName) - .openSession(); - entityManager.getTransaction() - .begin(); + if (sessionFactory == null) { + sessionFactory = HibernateUtil.getSessionFactory(propertyFileName); + } + EntityManager entityManager = sessionFactory.openSession(); + entityManager.getTransaction().begin(); return entityManager; } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/BasicPessimisticLockingIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/BasicPessimisticLockingIntegrationTest.java index f416c11d1f..4b9c7720fd 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/BasicPessimisticLockingIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/BasicPessimisticLockingIntegrationTest.java @@ -2,6 +2,9 @@ package com.baeldung.hibernate.pessimisticlocking; import com.baeldung.hibernate.HibernateUtil; import com.vividsolutions.jts.util.Assert; + +import org.hibernate.SessionFactory; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -10,6 +13,8 @@ import java.io.IOException; import java.util.Arrays; public class BasicPessimisticLockingIntegrationTest { + + private static SessionFactory sessionFactory; @BeforeClass public static void setUp() throws IOException { @@ -140,12 +145,18 @@ public class BasicPessimisticLockingIntegrationTest { protected static EntityManager getEntityManagerWithOpenTransaction() throws IOException { String propertyFileName = "hibernate-pessimistic-locking.properties"; - EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName) - .openSession(); - entityManager.getTransaction() - .begin(); + if (sessionFactory == null) { + sessionFactory = HibernateUtil.getSessionFactory(propertyFileName); + } + EntityManager entityManager = sessionFactory.openSession(); + entityManager.getTransaction().begin(); return entityManager; } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/PessimisticLockScopesIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/PessimisticLockScopesIntegrationTest.java index ac56ab7133..81cb7d95f8 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/PessimisticLockScopesIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/pessimisticlocking/PessimisticLockScopesIntegrationTest.java @@ -1,6 +1,9 @@ package com.baeldung.hibernate.pessimisticlocking; import com.baeldung.hibernate.HibernateUtil; + +import org.hibernate.SessionFactory; +import org.junit.AfterClass; import org.junit.Test; import javax.persistence.EntityManager; @@ -13,6 +16,8 @@ import java.util.HashMap; import java.util.Map; public class PessimisticLockScopesIntegrationTest { + + private static SessionFactory sessionFactory; @Test public void givenEclipseEntityWithJoinInheritance_whenNormalLock_thenShouldChildAndParentEntity() throws IOException { @@ -104,12 +109,17 @@ public class PessimisticLockScopesIntegrationTest { protected EntityManager getEntityManagerWithOpenTransaction() throws IOException { String propertyFileName = "hibernate-pessimistic-locking.properties"; - EntityManager entityManager = HibernateUtil.getSessionFactory(propertyFileName) - .openSession(); - entityManager.getTransaction() - .begin(); + if (sessionFactory == null) { + sessionFactory = HibernateUtil.getSessionFactory(propertyFileName); + } + EntityManager entityManager = sessionFactory.openSession(); + entityManager.getTransaction().begin(); return entityManager; } - + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java new file mode 100644 index 0000000000..13eae3d877 --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/queryplancache/QueryPlanCacheBenchmark.java @@ -0,0 +1,106 @@ +package com.baeldung.hibernate.queryplancache; + +import com.baeldung.hibernate.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.jpa.QueryHints; +import org.hibernate.query.Query; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.RunnerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +public class QueryPlanCacheBenchmark { + + private static final Logger LOGGER = LoggerFactory.getLogger(QueryPlanCacheBenchmark.class); + + @State(Scope.Thread) + public static class QueryPlanCacheBenchMarkState { + @Param({"1", "2", "3"}) + public int planCacheSize; + + public Session session; + + @Setup + public void stateSetup() throws IOException { + LOGGER.info("State - Setup"); + session = initSession(planCacheSize); + LOGGER.info("State - Setup Complete"); + } + + private Session initSession(int planCacheSize) throws IOException { + Properties properties = HibernateUtil.getProperties(); + properties.put("hibernate.query.plan_cache_max_size", planCacheSize); + properties.put("hibernate.query.plan_parameter_metadata_max_size", planCacheSize); + SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties); + return sessionFactory.openSession(); + } + + @TearDown + public void tearDownState() { + LOGGER.info("State - Teardown"); + SessionFactory sessionFactory = session.getSessionFactory(); + session.close(); + sessionFactory.close(); + LOGGER.info("State - Teardown complete"); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + @Fork(1) + @Warmup(iterations = 2) + @Measurement(iterations = 5) + public void givenQueryPlanCacheSize_thenCompileQueries(QueryPlanCacheBenchMarkState state, Blackhole blackhole) { + + Query query1 = findEmployeesByDepartmentNameQuery(state.session); + Query query2 = findEmployeesByDesignationQuery(state.session); + Query query3 = findDepartmentOfAnEmployeeQuery(state.session); + + blackhole.consume(query1); + blackhole.consume(query2); + blackhole.consume(query3); + + } + + private Query findEmployeesByDepartmentNameQuery(Session session) { + return session.createQuery("SELECT e FROM DeptEmployee e " + + "JOIN e.department WHERE e.department.name = :deptName") + .setMaxResults(30) + .setHint(QueryHints.HINT_FETCH_SIZE, 30); + } + + private Query findEmployeesByDesignationQuery(Session session) { + return session.createQuery("SELECT e FROM DeptEmployee e " + + "WHERE e.title = :designation") + .setHint(QueryHints.SPEC_HINT_TIMEOUT, 1000); + } + + private Query findDepartmentOfAnEmployeeQuery(Session session) { + return session.createQuery("SELECT e.department FROM DeptEmployee e " + + "JOIN e.department WHERE e.employeeNumber = :empId"); + + } + + public static void main(String... args) throws IOException, RunnerException { + //main-class to run the benchmark + org.openjdk.jmh.Main.main(args); + } +} 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); + } + + +} diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-customtypes.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-customtypes.properties index 345f3d37b0..c14782ce0f 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-customtypes.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-customtypes.properties @@ -1,10 +1,14 @@ -hibernate.connection.driver_class=org.postgresql.Driver -hibernate.connection.url=jdbc:postgresql://localhost:5432/test -hibernate.connection.username=postgres -hibernate.connection.password=thule +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa hibernate.connection.autocommit=true -jdbc.password=thule +jdbc.password= -hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.show_sql=true -hibernate.hbm2ddl.auto=create-drop \ No newline at end of file +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties new file mode 100644 index 0000000000..e08a23166d --- /dev/null +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties @@ -0,0 +1,16 @@ +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:myexceptiondb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 + +hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-pessimistic-locking.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-pessimistic-locking.properties index c76bd3358b..4f1ff5e93a 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-pessimistic-locking.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-pessimistic-locking.properties @@ -1,5 +1,5 @@ hibernate.connection.driver_class=org.h2.Driver -hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=100;MVCC=FALSE +hibernate.connection.url=jdbc:h2:mem:mydb3;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=100;MVCC=FALSE hibernate.connection.username=sa hibernate.connection.autocommit=true hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-spatial.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-spatial.properties index e85cd49cc3..1657c838e3 100644 --- a/persistence-modules/hibernate5/src/test/resources/hibernate-spatial.properties +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-spatial.properties @@ -1,10 +1,14 @@ -hibernate.dialect=org.hibernate.spatial.dialect.mysql.MySQL56SpatialDialect -hibernate.connection.driver_class=com.mysql.jdbc.Driver -hibernate.connection.url=jdbc:mysql://localhost:3306/hibernate-spatial -hibernate.connection.username=root -hibernate.connection.password=pass -hibernate.connection.pool_size=5 +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.spatial.dialect.h2geodb.GeoDBDialect hibernate.show_sql=true -hibernate.format_sql=true -hibernate.max_fetch_depth=5 -hibernate.hbm2ddl.auto=create-drop \ No newline at end of file +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 diff --git a/persistence-modules/influxdb/pom.xml b/persistence-modules/influxdb/pom.xml index 5043d61897..a8ecaadd62 100644 --- a/persistence-modules/influxdb/pom.xml +++ b/persistence-modules/influxdb/pom.xml @@ -4,8 +4,8 @@ 4.0.0 influxdb 0.1-SNAPSHOT - jar influxdb + jar InfluxDB SDK Tutorial @@ -33,7 +33,6 @@ 2.8 - 1.16.18 diff --git a/persistence-modules/java-cassandra/pom.xml b/persistence-modules/java-cassandra/pom.xml index aac5d49547..708d2b3c76 100644 --- a/persistence-modules/java-cassandra/pom.xml +++ b/persistence-modules/java-cassandra/pom.xml @@ -39,6 +39,7 @@ 3.1.2 3.1.1.0 + 18.0 diff --git a/persistence-modules/java-cockroachdb/pom.xml b/persistence-modules/java-cockroachdb/pom.xml index 2a92934a6e..2738ef85ff 100644 --- a/persistence-modules/java-cockroachdb/pom.xml +++ b/persistence-modules/java-cockroachdb/pom.xml @@ -5,7 +5,7 @@ com.baeldung java-cockroachdb 1.0-SNAPSHOT - java-cockroachdb + java-cockroachdb parent-modules @@ -22,15 +22,6 @@ - - - Central - Central - http://repo1.maven.org/maven2/ - default - - - 42.1.4 diff --git a/persistence-modules/java-jdbi/README.md b/persistence-modules/java-jdbi/README.md index 7d843af9ea..4c1ff931ce 100644 --- a/persistence-modules/java-jdbi/README.md +++ b/persistence-modules/java-jdbi/README.md @@ -1 +1,3 @@ ### Relevant Articles: + +- [A Guide to Jdbi](http://www.baeldung.com/jdbi) diff --git a/persistence-modules/java-jdbi/pom.xml b/persistence-modules/java-jdbi/pom.xml index 9281f4fd9d..dfb31b26e8 100644 --- a/persistence-modules/java-jdbi/pom.xml +++ b/persistence-modules/java-jdbi/pom.xml @@ -27,15 +27,6 @@ - - - Central - Central - http://repo1.maven.org/maven2/ - default - - - 3.1.0 2.4.0 diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md index 9a90216519..7edcd168e9 100644 --- a/persistence-modules/java-jpa/README.md +++ b/persistence-modules/java-jpa/README.md @@ -2,4 +2,14 @@ - [A Guide to SqlResultSetMapping](http://www.baeldung.com/jpa-sql-resultset-mapping) - [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures) -- [Fixing the JPA error “java.lang.String cannot be cast to [Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) +- [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) +- [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) +- [Types of JPA Queries](https://www.baeldung.com/jpa-queries) +- [JPA/Hibernate Projections](https://www.baeldung.com/jpa-hibernate-projections) +- [Composite Primary Keys in JPA](https://www.baeldung.com/jpa-composite-primary-keys) +- [Defining JPA Entities](https://www.baeldung.com/jpa-entities) +- [JPA @Basic Annotation](https://www.baeldung.com/jpa-basic-annotation) +- [Default Column Values in JPA](https://www.baeldung.com/jpa-default-column-values) diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml index ddab51a2e2..ced049d281 100644 --- a/persistence-modules/java-jpa/pom.xml +++ b/persistence-modules/java-jpa/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 java-jpa - java-jpa - + java-jpa + parent-modules com.baeldung @@ -19,15 +19,97 @@ hibernate-core ${hibernate.version} + + org.hibernate + hibernate-jpamodelgen + ${hibernate.version} + com.h2database h2 ${h2.version} + + + + javax.persistence + javax.persistence-api + ${javax.persistence-api.version} + + + + + org.eclipse.persistence + eclipselink + ${eclipselink.version} + runtime + + + org.postgresql + postgresql + ${postgres.version} + runtime + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + -proc:none + + + + org.bsc.maven + maven-processor-plugin + 3.3.3 + + + process + + process + + generate-sources + + target/metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add-source + generate-sources + + add-source + + + + target/metamodel + + + + + + + + - 5.3.1.Final - 1.4.197 + 5.4.0.Final + 2.7.4-RC1 + 42.2.5 + 2.2 + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java new file mode 100644 index 0000000000..cc5a83420c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java @@ -0,0 +1,33 @@ +package com.baeldung.jpa.basicannotation; + +import javax.persistence.Basic; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; + +@Entity +public class Course { + + @Id + private int id; + + @Basic(optional = false, fetch = FetchType.LAZY) + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + 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/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java new file mode 100644 index 0000000000..0bd04da221 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java @@ -0,0 +1,68 @@ +package com.baeldung.jpa.datetime; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.*; +import java.util.Calendar; + +public class DateTimeEntityRepository { + private EntityManagerFactory emf = null; + + public DateTimeEntityRepository() { + emf = Persistence.createEntityManagerFactory("java8-datetime-postgresql"); + } + + public JPA22DateTimeEntity find(Long id) { + EntityManager entityManager = emf.createEntityManager(); + + JPA22DateTimeEntity dateTimeTypes = entityManager.find(JPA22DateTimeEntity.class, id); + + entityManager.close(); + return dateTimeTypes; + } + + public void save(Long id) { + JPA22DateTimeEntity dateTimeTypes = new JPA22DateTimeEntity(); + dateTimeTypes.setId(id); + + //java.sql types: date/time + dateTimeTypes.setSqlTime(Time.valueOf(LocalTime.now())); + dateTimeTypes.setSqlDate(Date.valueOf(LocalDate.now())); + dateTimeTypes.setSqlTimestamp(Timestamp.valueOf(LocalDateTime.now())); + + //java.util types: date/calendar + java.util.Date date = new java.util.Date(); + dateTimeTypes.setUtilTime(date); + dateTimeTypes.setUtilDate(date); + dateTimeTypes.setUtilTimestamp(date); + + //Calendar + Calendar calendar = Calendar.getInstance(); + dateTimeTypes.setCalendarTime(calendar); + dateTimeTypes.setCalendarDate(calendar); + dateTimeTypes.setCalendarTimestamp(calendar); + + //java.time types + dateTimeTypes.setLocalTime(LocalTime.now()); + dateTimeTypes.setLocalDate(LocalDate.now()); + dateTimeTypes.setLocalDateTime(LocalDateTime.now()); + + //java.time types with offset + dateTimeTypes.setOffsetTime(OffsetTime.now()); + dateTimeTypes.setOffsetDateTime(OffsetDateTime.now()); + + EntityManager entityManager = emf.createEntityManager(); + entityManager.getTransaction().begin(); + entityManager.persist(dateTimeTypes); + entityManager.getTransaction().commit(); + entityManager.close(); + } + + public void clean() { + emf.close(); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java new file mode 100644 index 0000000000..065385bd86 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java @@ -0,0 +1,176 @@ +package com.baeldung.jpa.datetime; + +import javax.persistence.*; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.*; +import java.util.Calendar; + +@Entity +public class JPA22DateTimeEntity { + + @Id + private Long id; + + //java.sql types + private Time sqlTime; + private Date sqlDate; + private Timestamp sqlTimestamp; + + //java.util types + @Temporal(TemporalType.TIME) + private java.util.Date utilTime; + + @Temporal(TemporalType.DATE) + private java.util.Date utilDate; + + @Temporal(TemporalType.TIMESTAMP) + private java.util.Date utilTimestamp; + + //Calendar + @Temporal(TemporalType.TIME) + private Calendar calendarTime; + + @Temporal(TemporalType.DATE) + private Calendar calendarDate; + + @Temporal(TemporalType.TIMESTAMP) + private Calendar calendarTimestamp; + + // java.time types + @Column(name = "local_time", columnDefinition = "TIME") + private LocalTime localTime; + + @Column(name = "local_date", columnDefinition = "DATE") + private LocalDate localDate; + + @Column(name = "local_date_time", columnDefinition = "TIMESTAMP") + private LocalDateTime localDateTime; + + @Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE") + private OffsetTime offsetTime; + + @Column(name = "offset_date_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private OffsetDateTime offsetDateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Time getSqlTime() { + return sqlTime; + } + + public void setSqlTime(Time sqlTime) { + this.sqlTime = sqlTime; + } + + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Timestamp getSqlTimestamp() { + return sqlTimestamp; + } + + public void setSqlTimestamp(Timestamp sqlTimestamp) { + this.sqlTimestamp = sqlTimestamp; + } + + public java.util.Date getUtilTime() { + return utilTime; + } + + public void setUtilTime(java.util.Date utilTime) { + this.utilTime = utilTime; + } + + public java.util.Date getUtilDate() { + return utilDate; + } + + public void setUtilDate(java.util.Date utilDate) { + this.utilDate = utilDate; + } + + public java.util.Date getUtilTimestamp() { + return utilTimestamp; + } + + public void setUtilTimestamp(java.util.Date utilTimestamp) { + this.utilTimestamp = utilTimestamp; + } + + public Calendar getCalendarTime() { + return calendarTime; + } + + public void setCalendarTime(Calendar calendarTime) { + this.calendarTime = calendarTime; + } + + public Calendar getCalendarDate() { + return calendarDate; + } + + public void setCalendarDate(Calendar calendarDate) { + this.calendarDate = calendarDate; + } + + public Calendar getCalendarTimestamp() { + return calendarTimestamp; + } + + public void setCalendarTimestamp(Calendar calendarTimestamp) { + this.calendarTimestamp = calendarTimestamp; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java new file mode 100644 index 0000000000..7f23f44254 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java @@ -0,0 +1,18 @@ +package com.baeldung.jpa.datetime; + +public class MainApp { + + public static void main(String... args) { + + DateTimeEntityRepository dateTimeEntityRepository = new DateTimeEntityRepository(); + + //Persist + dateTimeEntityRepository.save(100L); + + //Find + JPA22DateTimeEntity dateTimeEntity = dateTimeEntityRepository.find(100L); + + dateTimeEntityRepository.clean(); + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java new file mode 100644 index 0000000000..436c708d40 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java @@ -0,0 +1,54 @@ +package com.baeldung.jpa.defaultvalues; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class User { + + @Id + private Long id; + + @Column(columnDefinition = "varchar(255) default 'John Snow'") + private String name = "John Snow"; + + @Column(columnDefinition = "integer default 25") + private Integer age = 25; + + @Column(columnDefinition = "boolean default false") + private Boolean locked = false; + + 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 Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Boolean getLocked() { + return locked; + } + + public void setLocked(Boolean locked) { + this.locked = locked; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java new file mode 100644 index 0000000000..52f9807cfb --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java @@ -0,0 +1,36 @@ +package com.baeldung.jpa.defaultvalues; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class UserRepository { + + private EntityManagerFactory emf = null; + + public UserRepository() { + emf = Persistence.createEntityManagerFactory("entity-default-values"); + } + + public User find(Long id) { + EntityManager entityManager = emf.createEntityManager(); + User user = entityManager.find(User.class, id); + entityManager.close(); + return user; + } + + public void save(User user, Long id) { + user.setId(id); + + EntityManager entityManager = emf.createEntityManager(); + entityManager.getTransaction().begin(); + entityManager.persist(user); + entityManager.getTransaction().commit(); + entityManager.close(); + } + + public void clean() { + emf.close(); + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Account.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Account.java new file mode 100644 index 0000000000..48a98512fa --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Account.java @@ -0,0 +1,43 @@ +package com.baeldung.jpa.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +@Entity +@IdClass(AccountId.class) +public class Account { + + @Id + private String accountNumber; + + @Id + private String accountType; + + private String description; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/AccountId.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/AccountId.java new file mode 100644 index 0000000000..091c326367 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/AccountId.java @@ -0,0 +1,52 @@ +package com.baeldung.jpa.entity; + +import java.io.Serializable; + +public class AccountId implements Serializable { + + private static final long serialVersionUID = 1L; + + private String accountNumber; + private String accountType; + + public AccountId() { + + } + + public AccountId(String accountNumber, String accountType) { + this.accountNumber = accountNumber; + this.accountType = accountType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((accountNumber == null) ? 0 : accountNumber.hashCode()); + result = prime * result + ((accountType == null) ? 0 : accountType.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; + AccountId other = (AccountId) obj; + if (accountNumber == null) { + if (other.accountNumber != null) + return false; + } else if (!accountNumber.equals(other.accountNumber)) + return false; + if (accountType == null) { + if (other.accountType != null) + return false; + } else if (!accountType.equals(other.accountType)) + return false; + return true; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Book.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Book.java new file mode 100644 index 0000000000..460f302e28 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Book.java @@ -0,0 +1,34 @@ +package com.baeldung.jpa.entity; + +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +@Entity +public class Book { + + @EmbeddedId + private BookId bookId; + + private String description; + + public Book() { + + } + + public Book(BookId bookId) { + this.bookId = bookId; + } + + public BookId getBookId() { + return bookId; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/BookId.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/BookId.java new file mode 100644 index 0000000000..ff587beaf2 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/BookId.java @@ -0,0 +1,62 @@ +package com.baeldung.jpa.entity; + +import java.io.Serializable; + +import javax.persistence.Embeddable; + +@Embeddable +public class BookId implements Serializable { + + private static final long serialVersionUID = 1L; + private String title; + private String language; + + public BookId() { + + } + + public BookId(String title, String language) { + this.title = title; + this.language = language; + } + + public String getTitle() { + return title; + } + + public String getLanguage() { + return language; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((language == null) ? 0 : language.hashCode()); + result = prime * result + ((title == null) ? 0 : title.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; + BookId other = (BookId) obj; + if (language == null) { + if (other.language != null) + return false; + } else if (!language.equals(other.language)) + return false; + if (title == null) { + if (other.title != null) + return false; + } else if (!title.equals(other.title)) + return false; + return true; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java new file mode 100644 index 0000000000..531bae40c5 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/entity/Student.java @@ -0,0 +1,75 @@ +package com.baeldung.jpa.entity; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; + +import com.baeldung.util.Gender; + +@Entity +@Table(name="STUDENT") +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + @Column(name = "STUDENT_NAME", length = 50, nullable = false, unique = false) + private String name; + @Transient + private Integer age; + @Temporal(TemporalType.DATE) + private Date birthDate; + @Enumerated(EnumType.STRING) + private Gender gender; + + 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 Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java new file mode 100644 index 0000000000..d534f44e14 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java @@ -0,0 +1,91 @@ +package com.baeldung.jpa.enums; + +import javax.persistence.*; + +@Entity +public class Article { + + @Id + private int id; + + private String title; + + @Enumerated(EnumType.ORDINAL) + private Status status; + + @Enumerated(EnumType.STRING) + private Type type; + + @Basic + private int priorityValue; + + @Transient + private Priority priority; + + private Category category; + + public Article() { + } + + @PostLoad + void fillTransient() { + if (priorityValue > 0) { + this.priority = Priority.of(priorityValue); + } + } + + @PrePersist + void fillPersistent() { + if (priority != null) { + this.priorityValue = priority.getPriority(); + } + } + + 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 Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java new file mode 100644 index 0000000000..83b81da01e --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java @@ -0,0 +1,17 @@ +package com.baeldung.jpa.enums; + +import java.util.stream.Stream; + +public enum Category { + SPORT("S"), MUSIC("M"), TECHNOLOGY("T"); + + private String code; + + Category(String code) { + this.code = code; + } + + public String getCode() { + return code; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java new file mode 100644 index 0000000000..98960f1569 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java @@ -0,0 +1,28 @@ +package com.baeldung.jpa.enums; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.util.stream.Stream; + +@Converter(autoApply = true) +public class CategoryConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(Category category) { + if (category == null) { + return null; + } + return category.getCode(); + } + + @Override + public Category convertToEntityAttribute(final String code) { + if (code == null) { + return null; + } + + return Stream.of(Category.values()) + .filter(c -> c.getCode().equals(code)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java new file mode 100644 index 0000000000..42ee254303 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java @@ -0,0 +1,24 @@ +package com.baeldung.jpa.enums; + +import java.util.stream.Stream; + +public enum Priority { + LOW(100), MEDIUM(200), HIGH(300); + + private int priority; + + private Priority(int priority) { + this.priority = priority; + } + + public int getPriority() { + return priority; + } + + public static Priority of(int priority) { + return Stream.of(Priority.values()) + .filter(p -> p.getPriority() == priority) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java new file mode 100644 index 0000000000..80d5662c7a --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java @@ -0,0 +1,5 @@ +package com.baeldung.jpa.enums; + +public enum Status { + OPEN, REVIEW, APPROVED, REJECTED; +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java new file mode 100644 index 0000000000..80459fbd3c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java @@ -0,0 +1,5 @@ +package com.baeldung.jpa.enums; + +enum Type { + INTERNAL, EXTERNAL; +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/Product.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/Product.java new file mode 100644 index 0000000000..90f90be0c0 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/Product.java @@ -0,0 +1,50 @@ +package com.baeldung.jpa.projections; + +import java.math.BigDecimal; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Product { + @Id + private long id; + private String name; + private String description; + private String category; + private BigDecimal unitPrice; + + 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 getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public String getCategory() { + return category; + } + public void setCategory(String category) { + this.category = category; + } + public BigDecimal getUnitPrice() { + return unitPrice; + } + public void setUnitPrice(BigDecimal unitPrice) { + this.unitPrice = unitPrice; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/ProductRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/ProductRepository.java new file mode 100644 index 0000000000..bb269e1de6 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/projections/ProductRepository.java @@ -0,0 +1,93 @@ +package com.baeldung.jpa.projections; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +public class ProductRepository { + private EntityManager entityManager; + + public ProductRepository() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-projections"); + entityManager = factory.createEntityManager(); + } + + @SuppressWarnings("unchecked") + public List findAllNamesUsingJPQL() { + Query query = entityManager.createQuery("select name from Product"); + List resultList = query.getResultList(); + return resultList; + } + + @SuppressWarnings("unchecked") + public List findAllIdsUsingJPQL() { + Query query = entityManager.createQuery("select id from Product"); + List resultList = query.getResultList(); + return resultList; + } + + public List findAllNamesUsingCriteriaBuilder() { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(String.class); + Root product = query.from(Product.class); + query.select(product.get("name")); + List resultList = entityManager.createQuery(query).getResultList(); + return resultList; + } + + @SuppressWarnings("unchecked") + public List findAllIdAndNamesUsingJPQL() { + Query query = entityManager.createQuery("select id, name from Product"); + List resultList = query.getResultList(); + return resultList; + } + + public List findAllIdAndNamesUsingCriteriaBuilderArray() { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(Object[].class); + Root product = query.from(Product.class); + query.select(builder.array(product.get("id"), product.get("name"))); + List resultList = entityManager.createQuery(query).getResultList(); + return resultList; + } + + public List findAllIdNameUnitPriceUsingCriteriaQueryMultiselect() { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(Object[].class); + Root product = query.from(Product.class); + query.multiselect(product.get("id"), product.get("name"), product.get("unitPrice")); + List resultList = entityManager.createQuery(query).getResultList(); + return resultList; + } + + public List findAllIdAndNamesUsingCriteriaBuilderTuple() { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(Tuple.class); + Root product = query.from(Product.class); + query.select(builder.tuple(product.get("id"), product.get("name"))); + List resultList = entityManager.createQuery(query).getResultList(); + return resultList; + } + + public List findCountByCategoryUsingJPQL() { + Query query = entityManager.createQuery("select p.category, count(p) from Product p group by p.category"); + return query.getResultList(); + } + + public List findCountByCategoryUsingCriteriaBuilder() { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(Object[].class); + Root product = query.from(Product.class); + query.multiselect(product.get("category"), builder.count(product)); + query.groupBy(product.get("category")); + List resultList = entityManager.createQuery(query).getResultList(); + return resultList; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java new file mode 100644 index 0000000000..bf3d459530 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java @@ -0,0 +1,79 @@ +package com.baeldung.jpa.queryparams; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "employees") +public class Employee { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "employee_number", unique = true) + private String empNumber; + + @Column(name = "employee_name") + private String name; + + @Column(name = "employee_age") + private int age; + + public Employee() { + super(); + } + + public Employee(Long id, String empNumber) { + super(); + this.id = id; + this.empNumber = empNumber; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmpNumber() { + return empNumber; + } + + public void setEmpNumber(String empNumber) { + this.empNumber = empNumber; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + +} 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/java/com/baeldung/util/Gender.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/Gender.java new file mode 100644 index 0000000000..13f08d995c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/Gender.java @@ -0,0 +1,6 @@ +package com.baeldung.util; + +public enum Gender { + MALE, + FEMALE +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java new file mode 100644 index 0000000000..00fd378b05 --- /dev/null +++ b/persistence-modules/java-jpa/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/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 433d456cc9..6a236f0840 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,69 +1,249 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence + http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd" + version="2.2"> - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.sqlresultsetmapping.ScheduledDay - - - - - - - - - - - + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.sqlresultsetmapping.ScheduledDay + com.baeldung.sqlresultsetmapping.Employee + com.baeldung.jpa.basicannotation.Course + true + + + + + + + + + + + - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.stringcast.Message - - - - - - - - - - - + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.stringcast.Message + com.baeldung.jpa.enums.Article + com.baeldung.jpa.enums.CategoryConverter + true + + + + + + + + + + + - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.model.Car - - - - - - - - - + + 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 - + + 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 + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.querytypes.UserEntity + true + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.defaultvalues.User + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.entity.Student + com.baeldung.jpa.entity.Book + com.baeldung.jpa.entity.BookId + com.baeldung.jpa.entity.Account + com.baeldung.jpa.entity.AccountId + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.projections.Product + true + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.queryparams.Employee + true + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/resources/database.sql b/persistence-modules/java-jpa/src/main/resources/database.sql index bd2bb68599..96fa5b3b09 100644 --- a/persistence-modules/java-jpa/src/main/resources/database.sql +++ b/persistence-modules/java-jpa/src/main/resources/database.sql @@ -15,3 +15,7 @@ INSERT INTO SCHEDULE_DAYS (employeeId, dayOfWeek) VALUES (1, 'FRIDAY'); INSERT INTO SCHEDULE_DAYS (employeeId, dayOfWeek) VALUES (2, 'SATURDAY'); INSERT INTO SCHEDULE_DAYS (employeeId, dayOfWeek) VALUES (3, 'MONDAY'); INSERT INTO SCHEDULE_DAYS (employeeId, dayOfWeek) VALUES (3, 'FRIDAY'); + +CREATE TABLE COURSE +(id BIGINT, + name VARCHAR(10)); \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/resources/products_jpa.sql b/persistence-modules/java-jpa/src/main/resources/products_jpa.sql new file mode 100644 index 0000000000..43bc294f56 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/resources/products_jpa.sql @@ -0,0 +1,4 @@ +insert into product(id, name, description, category) values (1,'Product Name 1','This is Product 1', 'category1'); +insert into product(id, name, description, category) values (2,'Product Name 2','This is Product 2', 'category1'); +insert into product(id, name, description, category) values (3,'Product Name 3','This is Product 3', 'category2'); +insert into product(id, name, description, category) values (4,'Product Name 4','This is Product 4', 'category3'); diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java new file mode 100644 index 0000000000..d3f75804de --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.jpa.basicannotation; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.PersistenceException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BasicAnnotationIntegrationTest { + + private static EntityManager entityManager; + private static EntityManagerFactory entityManagerFactory; + + @BeforeClass + public static void setup() { + entityManagerFactory = Persistence.createEntityManagerFactory("java-jpa-scheduled-day"); + entityManager = entityManagerFactory.createEntityManager(); + entityManager.getTransaction().begin(); + } + + @Test + public void givenACourse_whenCourseNamePresent_shouldPersist() { + Course course = new Course(); + course.setName("Computers"); + + entityManager.persist(course); + entityManager.flush(); + entityManager.clear(); + + } + + @Test(expected = PersistenceException.class) + public void givenACourse_whenCourseNameAbsent_shouldFail() { + Course course = new Course(); + + entityManager.persist(course); + entityManager.flush(); + entityManager.clear(); + } + + @AfterClass + public static void destroy() { + + if (entityManager != null) { + entityManager.close(); + } + if (entityManagerFactory != null) { + entityManagerFactory.close(); + } + } +} 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/java/com/baeldung/jpa/defaultvalues/UserDefaultValuesUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/defaultvalues/UserDefaultValuesUnitTest.java new file mode 100644 index 0000000000..dc41ff51f2 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/defaultvalues/UserDefaultValuesUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.jpa.defaultvalues; + +import com.baeldung.jpa.defaultvalues.User; +import com.baeldung.jpa.defaultvalues.UserRepository; + +import org.junit.Test; +import org.junit.Ignore; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import static org.junit.Assert.*; + +public class UserDefaultValuesUnitTest { + + private static UserRepository userRepository = null; + + @BeforeClass + public static void once() { + userRepository = new UserRepository(); + } + + @Test + @Ignore // SQL default values are also defined + public void saveUser_shouldSaveWithDefaultFieldValues() { + User user = new User(); + userRepository.save(user, 1L); + + user = userRepository.find(1L); + assertEquals(user.getName(), "John Snow"); + assertEquals(25, (int) user.getAge()); + assertFalse(user.getLocked()); + } + + @Test + @Ignore // SQL default values are also defined + public void saveUser_shouldSaveWithNullName() { + User user = new User(); + user.setName(null); + userRepository.save(user, 2L); + + user = userRepository.find(2L); + assertNull(user.getName()); + assertEquals(25, (int) user.getAge()); + assertFalse(user.getLocked()); + } + + @Test + public void saveUser_shouldSaveWithDefaultSqlValues() { + User user = new User(); + userRepository.save(user, 3L); + + user = userRepository.find(3L); + assertEquals(user.getName(), "John Snow"); + assertEquals(25, (int) user.getAge()); + assertFalse(user.getLocked()); + } + + @AfterClass + public static void destroy() { + userRepository.clean(); + } + +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/CompositeKeysIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/CompositeKeysIntegrationTest.java new file mode 100644 index 0000000000..2d30ebab5e --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/CompositeKeysIntegrationTest.java @@ -0,0 +1,114 @@ +package com.baeldung.jpa.entity; + +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class CompositeKeysIntegrationTest { + + private static final String SAVINGS_ACCOUNT = "Savings"; + private static final String ACCOUNT_NUMBER = "JXSDF324234"; + private static final String ENGLISH = "English"; + private static final String WAR_AND_PEACE = "War and Peace"; + + private static EntityManagerFactory emf; + private static EntityManager em; + + @BeforeClass + public static void setup() { + emf = Persistence.createEntityManagerFactory("jpa-entity-definition"); + em = emf.createEntityManager(); + } + + @Test + public void persistBookWithCompositeKeyThenRetrieveDetails() { + Book warAndPeace = createBook(); + persist(warAndPeace); + clearThePersistenceContext(); + Book book = findBookByBookId(); + verifyAssertionsWith(book); + } + + @Test + public void persistAccountWithCompositeKeyThenRetrieveDetails() { + Account savingsAccount = createAccount(); + persist(savingsAccount); + clearThePersistenceContext(); + Account account = findAccountByAccountId(); + verifyAssertionsWith(account); + } + + @AfterClass + public static void destroy() { + if (em != null) { + em.close(); + } + if (emf != null) { + emf.close(); + } + } + + private Account createAccount() { + Account savingsAccount = new Account(); + savingsAccount.setAccountNumber(ACCOUNT_NUMBER); + savingsAccount.setAccountType(SAVINGS_ACCOUNT); + savingsAccount.setDescription("Savings account"); + return savingsAccount; + } + + private void verifyAssertionsWith(Account account) { + assertEquals(ACCOUNT_NUMBER, account.getAccountNumber()); + assertEquals(SAVINGS_ACCOUNT, account.getAccountType()); + } + + private Account findAccountByAccountId() { + return em.find(Account.class, new AccountId(ACCOUNT_NUMBER, SAVINGS_ACCOUNT)); + } + + private void persist(Account account) { + em.getTransaction() + .begin(); + em.persist(account); + em.getTransaction() + .commit(); + } + + private Book findBookByBookId() { + return em.find(Book.class, new BookId(WAR_AND_PEACE, ENGLISH)); + } + + private Book createBook() { + BookId bookId = new BookId(WAR_AND_PEACE, ENGLISH); + Book warAndPeace = new Book(bookId); + warAndPeace.setDescription("Novel and Historical Fiction"); + return warAndPeace; + } + + private void verifyAssertionsWith(Book book) { + assertNotNull(book); + assertNotNull(book.getBookId()); + assertEquals(WAR_AND_PEACE, book.getBookId() + .getTitle()); + assertEquals(ENGLISH, book.getBookId() + .getLanguage()); + } + + private void persist(Book book) { + em.getTransaction() + .begin(); + em.persist(book); + em.getTransaction() + .commit(); + } + + private void clearThePersistenceContext() { + em.clear(); + } +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java new file mode 100644 index 0000000000..fdaaba5439 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/entity/StudentEntityIntegrationTest.java @@ -0,0 +1,91 @@ +package com.baeldung.jpa.entity; + +import static org.junit.Assert.assertEquals; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.util.Gender; + +public class StudentEntityIntegrationTest { + + private EntityManagerFactory emf; + private EntityManager em; + + @Before + public void setup() { + emf = Persistence.createEntityManagerFactory("jpa-entity-definition"); + em = emf.createEntityManager(); + } + + @Test + public void persistStudentThenRetrieveTheDetails() { + Student student = createStudentWithRelevantDetails(); + persist(student); + clearThePersistenceContext(); + List students = getStudentsFromTable(); + checkAssertionsWith(students); + } + + @After + public void destroy() { + if (em != null) { + em.close(); + } + if (emf != null) { + emf.close(); + } + } + + private void clearThePersistenceContext() { + em.clear(); + } + + private void checkAssertionsWith(List students) { + assertEquals(1, students.size()); + Student john = students.get(0); + assertEquals(1L, john.getId().longValue()); + assertEquals(null, john.getAge()); + assertEquals("John", john.getName()); + } + + private List getStudentsFromTable() { + String selectQuery = "SELECT student FROM Student student"; + TypedQuery selectFromStudentTypedQuery = em.createQuery(selectQuery, Student.class); + List students = selectFromStudentTypedQuery.getResultList(); + return students; + } + + private void persist(Student student) { + em.getTransaction().begin(); + em.persist(student); + em.getTransaction().commit(); + } + + private Student createStudentWithRelevantDetails() { + Student student = new Student(); + student.setAge(20); // the 'age' field has been annotated with @Transient + student.setName("John"); + Date date = getDate(); + student.setBirthDate(date); + student.setGender(Gender.MALE); + return student; + } + + private Date getDate() { + LocalDate localDate = LocalDate.of(2008, 7, 20); + return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + } + +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java new file mode 100644 index 0000000000..82f3abc04d --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.jpa.enums; + +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ArticleUnitTest { + + private static EntityManager em; + private static EntityManagerFactory emFactory; + + @BeforeClass + public static void setup() { + Map properties = new HashMap(); + properties.put("hibernate.show_sql", "true"); + properties.put("hibernate.format_sql", "true"); + emFactory = Persistence.createEntityManagerFactory("jpa-h2", properties); + em = emFactory.createEntityManager(); + } + + @Test + public void shouldPersistStatusEnumOrdinalValue() { + // given + Article article = new Article(); + article.setId(1); + article.setTitle("ordinal title"); + article.setStatus(Status.OPEN); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 1); + + assertEquals(1, persistedArticle.getId()); + assertEquals("ordinal title", persistedArticle.getTitle()); + assertEquals(Status.OPEN, persistedArticle.getStatus()); + } + + @Test + public void shouldPersistTypeEnumStringValue() { + // given + Article article = new Article(); + article.setId(2); + article.setTitle("string title"); + article.setType(Type.EXTERNAL); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 2); + + assertEquals(2, persistedArticle.getId()); + assertEquals("string title", persistedArticle.getTitle()); + assertEquals(Type.EXTERNAL, persistedArticle.getType()); + } + + @Test + public void shouldPersistPriorityIntValue() { + // given + Article article = new Article(); + article.setId(3); + article.setTitle("callback title"); + article.setPriority(Priority.HIGH); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 3); + + assertEquals(3, persistedArticle.getId()); + assertEquals("callback title", persistedArticle.getTitle()); + assertEquals(Priority.HIGH, persistedArticle.getPriority()); + + } + + @Test + public void shouldPersistCategoryEnumConvertedValue() { + // given + Article article = new Article(); + article.setId(4); + article.setTitle("converted title"); + article.setCategory(Category.MUSIC); + + // when + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + // then + Article persistedArticle = em.find(Article.class, 4); + + assertEquals(4, persistedArticle.getId()); + assertEquals("converted title", persistedArticle.getTitle()); + assertEquals(Category.MUSIC, persistedArticle.getCategory()); + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/HibernateProjectionsIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/HibernateProjectionsIntegrationTest.java new file mode 100644 index 0000000000..47cc7cbaec --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/HibernateProjectionsIntegrationTest.java @@ -0,0 +1,133 @@ +package com.baeldung.jpa.projections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Projections; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class HibernateProjectionsIntegrationTest { + private static Session session; + private static SessionFactory sessionFactory; + private Transaction transaction; + + @BeforeClass + public static void init() { + Configuration configuration = getConfiguration(); + configuration.addAnnotatedClass(Product.class); + sessionFactory = configuration.buildSessionFactory(); + } + + @Before + public void before() { + session = sessionFactory.getCurrentSession(); + transaction = session.beginTransaction(); + } + + @After + public void after() { + if(transaction.isActive()) { + transaction.rollback(); + } + } + + private static Configuration getConfiguration() { + Configuration cfg = new Configuration(); + cfg.setProperty(AvailableSettings.DIALECT, + "org.hibernate.dialect.H2Dialect"); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); + cfg.setProperty(AvailableSettings.DRIVER, "org.h2.Driver"); + cfg.setProperty(AvailableSettings.URL, + "jdbc:h2:mem:myexceptiondb2;DB_CLOSE_DELAY=-1;;INIT=RUNSCRIPT FROM 'src/test/resources/products.sql'"); + cfg.setProperty(AvailableSettings.USER, "sa"); + cfg.setProperty(AvailableSettings.PASS, ""); + cfg.setProperty(AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, "thread"); + return cfg; + } + + + @SuppressWarnings("deprecation") + @Test + public void givenProductData_whenIdAndNameProjectionUsingCriteria_thenListOfObjectArrayReturned() { + Criteria criteria = session.createCriteria(Product.class); + criteria = criteria.setProjection(Projections.projectionList() + .add(Projections.id()) + .add(Projections.property("name"))); + List resultList = criteria.list(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals(1L, resultList.get(0)[0]); + assertEquals("Product Name 1", resultList.get(0)[1]); + assertEquals(2L, resultList.get(1)[0]); + assertEquals("Product Name 2", resultList.get(1)[1]); + assertEquals(3L, resultList.get(2)[0]); + assertEquals("Product Name 3", resultList.get(2)[1]); + assertEquals(4L, resultList.get(3)[0]); + assertEquals("Product Name 4", resultList.get(3)[1]); + } + + + @Test + public void givenProductData_whenNameProjectionUsingCriteria_thenListOfStringReturned() { + Criteria criteria = session.createCriteria(Product.class); + criteria = criteria.setProjection(Projections.property("name")); + List resultList = criteria.list(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals("Product Name 1", resultList.get(0)); + assertEquals("Product Name 2", resultList.get(1)); + assertEquals("Product Name 3", resultList.get(2)); + assertEquals("Product Name 4", resultList.get(3)); + } + + @Test + public void givenProductData_whenCountByCategoryUsingCriteria_thenOK() { + Criteria criteria = session.createCriteria(Product.class); + criteria = criteria.setProjection(Projections.projectionList() + .add(Projections.groupProperty("category")) + .add(Projections.rowCount())); + List resultList = criteria.list(); + + assertNotNull(resultList); + assertEquals(3, resultList.size()); + assertEquals("category1", resultList.get(0)[0]); + assertEquals(2L, resultList.get(0)[1]); + assertEquals("category2", resultList.get(1)[0]); + assertEquals(1L, resultList.get(1)[1]); + assertEquals("category3", resultList.get(2)[0]); + assertEquals(1L, resultList.get(2)[1]); + } + + @Test + public void givenProductData_whenCountByCategoryWithAliasUsingCriteria_thenOK() { + Criteria criteria = session.createCriteria(Product.class); + criteria = criteria.setProjection(Projections.projectionList() + .add(Projections.groupProperty("category")) + .add(Projections.alias(Projections.rowCount(), "count"))); + criteria.addOrder(Order.asc("count")); + List resultList = criteria.list(); + + assertNotNull(resultList); + assertEquals(3, resultList.size()); + assertEquals("category2", resultList.get(0)[0]); + assertEquals(1L, resultList.get(0)[1]); + assertEquals("category3", resultList.get(1)[0]); + assertEquals(1L, resultList.get(1)[1]); + assertEquals("category1", resultList.get(2)[0]); + assertEquals(2L, resultList.get(2)[1]); + } +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/ProductRepositoryIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..c9a05709e3 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/projections/ProductRepositoryIntegrationTest.java @@ -0,0 +1,105 @@ +package com.baeldung.jpa.projections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + + +public class ProductRepositoryIntegrationTest { + private static ProductRepository productRepository; + + @BeforeClass + public static void once() throws IOException { + productRepository = new ProductRepository(); + } + + @Test + public void givenProductData_whenIdAndNameProjectionUsingJPQL_thenListOfObjectArrayReturned() { + List resultList = productRepository.findAllIdAndNamesUsingJPQL(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals(1L, resultList.get(0)[0]); + assertEquals("Product Name 1", resultList.get(0)[1]); + assertEquals(2L, resultList.get(1)[0]); + assertEquals("Product Name 2", resultList.get(1)[1]); + assertEquals(3L, resultList.get(2)[0]); + assertEquals("Product Name 3", resultList.get(2)[1]); + assertEquals(4L, resultList.get(3)[0]); + assertEquals("Product Name 4", resultList.get(3)[1]); + } + + @Test + public void givenProductData_whenIdAndNameProjectionUsingCriteriaBuilder_thenListOfObjectArrayReturned() { + List resultList = productRepository.findAllIdAndNamesUsingCriteriaBuilderArray(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals(1L, resultList.get(0)[0]); + assertEquals("Product Name 1", resultList.get(0)[1]); + assertEquals(2L, resultList.get(1)[0]); + assertEquals("Product Name 2", resultList.get(1)[1]); + assertEquals(3L, resultList.get(2)[0]); + assertEquals("Product Name 3", resultList.get(2)[1]); + assertEquals(4L, resultList.get(3)[0]); + assertEquals("Product Name 4", resultList.get(3)[1]); + } + + @SuppressWarnings("rawtypes") + @Test + public void givenProductData_whenNameProjectionUsingJPQL_thenListOfStringReturned() { + List resultList = productRepository.findAllNamesUsingJPQL(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals("Product Name 1", resultList.get(0)); + assertEquals("Product Name 2", resultList.get(1)); + assertEquals("Product Name 3", resultList.get(2)); + assertEquals("Product Name 4", resultList.get(3)); + } + + @Test + public void givenProductData_whenNameProjectionUsingCriteriaBuilder_thenListOfStringReturned() { + List resultList = productRepository.findAllNamesUsingCriteriaBuilder(); + + assertNotNull(resultList); + assertEquals(4, resultList.size()); + assertEquals("Product Name 1", resultList.get(0)); + assertEquals("Product Name 2", resultList.get(1)); + assertEquals("Product Name 3", resultList.get(2)); + assertEquals("Product Name 4", resultList.get(3)); + } + + @Test + public void givenProductData_whenCountByCategoryUsingJPQL_thenOK() { + List resultList = productRepository.findCountByCategoryUsingJPQL(); + + assertNotNull(resultList); + assertEquals(3, resultList.size()); + assertEquals("category1", resultList.get(0)[0]); + assertEquals(2L, resultList.get(0)[1]); + assertEquals("category2", resultList.get(1)[0]); + assertEquals(1L, resultList.get(1)[1]); + assertEquals("category3", resultList.get(2)[0]); + assertEquals(1L, resultList.get(2)[1]); + } + + @Test + public void givenProductData_whenCountByCategoryUsingCriteriaBuider_thenOK() { + List resultList = productRepository.findCountByCategoryUsingCriteriaBuilder(); + + assertNotNull(resultList); + assertEquals(3, resultList.size()); + assertEquals("category1", resultList.get(0)[0]); + assertEquals(2L, resultList.get(0)[1]); + assertEquals("category2", resultList.get(1)[0]); + assertEquals(1L, resultList.get(1)[1]); + assertEquals("category3", resultList.get(2)[0]); + assertEquals(1L, resultList.get(2)[1]); + } +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java new file mode 100644 index 0000000000..4f320935cf --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java @@ -0,0 +1,109 @@ +package com.baeldung.jpa.queryparams; + +import java.util.Arrays; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.ParameterExpression; +import javax.persistence.criteria.Root; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * JPAQueryParamsTest class tests. + * + * @author gmlopez.mackinnon@gmail.com + */ +public class JPAQueryParamsUnitTest { + + private static EntityManager entityManager; + + @BeforeClass + public static void setup() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-queryparams"); + entityManager = factory.createEntityManager(); + } + + @Test + public void givenEmpNumber_whenUsingPositionalParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = ?1", Employee.class); + String empNumber = "A123"; + Employee employee = query.setParameter(1, empNumber) + .getSingleResult(); + Assert.assertNotNull("Employee not found", employee); + } + + @Test + public void givenEmpNumberList_whenUsingPositionalParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber IN (?1)", Employee.class); + List empNumbers = Arrays.asList("A123", "A124"); + List employees = query.setParameter(1, empNumbers) + .getResultList(); + Assert.assertNotNull("Employees not found", employees); + Assert.assertFalse("Employees not found", employees.isEmpty()); + } + + @Test + public void givenEmpNumber_whenUsingNamedParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = :number", Employee.class); + String empNumber = "A123"; + Employee employee = query.setParameter("number", empNumber) + .getSingleResult(); + Assert.assertNotNull("Employee not found", employee); + } + + @Test + public void givenEmpNumberList_whenUsingNamedParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber IN (:numbers)", Employee.class); + List empNumbers = Arrays.asList("A123", "A124"); + List employees = query.setParameter("numbers", empNumbers) + .getResultList(); + Assert.assertNotNull("Employees not found", employees); + Assert.assertFalse("Employees not found", employees.isEmpty()); + } + + @Test + public void givenEmpNameAndEmpAge_whenUsingTwoNamedParameters_thenReturnExpectedEmployees() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.name = :name AND e.age = :empAge", Employee.class); + String empName = "John Doe"; + int empAge = 55; + List employees = query.setParameter("name", empName) + .setParameter("empAge", empAge) + .getResultList(); + Assert.assertNotNull("Employees not found!", employees); + Assert.assertTrue("Employees not found!", !employees.isEmpty()); + } + + @Test + public void givenEmpNumber_whenUsingCriteriaQuery_thenReturnExpectedEmployee() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery cQuery = cb.createQuery(Employee.class); + Root c = cQuery.from(Employee.class); + ParameterExpression paramEmpNumber = cb.parameter(String.class); + cQuery.select(c) + .where(cb.equal(c.get(Employee_.empNumber), paramEmpNumber)); + + TypedQuery query = entityManager.createQuery(cQuery); + String empNumber = "A123"; + query.setParameter(paramEmpNumber, empNumber); + Employee employee = query.getSingleResult(); + Assert.assertNotNull("Employee not found!", employee); + } + + @Test + public void givenEmpNumber_whenUsingLiteral_thenReturnExpectedEmployee() { + String empNumber = "A123"; + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = '" + empNumber + "'", Employee.class); + Employee employee = query.getSingleResult(); + Assert.assertNotNull("Employee not found!", employee); + } + +} 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/employees2.sql b/persistence-modules/java-jpa/src/test/resources/employees2.sql new file mode 100644 index 0000000000..d3ae46f6a0 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/resources/employees2.sql @@ -0,0 +1,2 @@ +INSERT INTO employees (employee_number, employee_name, employee_age) VALUES ('111', 'John Doe', 55); +INSERT INTO employees (employee_number, employee_name, employee_age) VALUES ('A123', 'John Doe Junior', 25); \ No newline at end of file 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/java-jpa/src/test/resources/products.sql b/persistence-modules/java-jpa/src/test/resources/products.sql new file mode 100644 index 0000000000..d38ea1b037 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/resources/products.sql @@ -0,0 +1,5 @@ +create table Product (id bigint not null, category varchar(255), description varchar(255), name varchar(255), unitPrice decimal(19,2), primary key (id)); +insert into product(id, name, description, category) values (1,'Product Name 1','This is Product 1', 'category1'); +insert into product(id, name, description, category) values (2,'Product Name 2','This is Product 2', 'category1'); +insert into product(id, name, description, category) values (3,'Product Name 3','This is Product 3', 'category2'); +insert into product(id, name, description, category) values (4,'Product Name 4','This is Product 4', 'category3'); 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'); diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md index ded2b220f1..045b245030 100644 --- a/persistence-modules/java-mongodb/README.md +++ b/persistence-modules/java-mongodb/README.md @@ -2,3 +2,5 @@ - [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb) - [A Simple Tagging Implementation with MongoDB](http://www.baeldung.com/mongodb-tagging) +- [MongoDB BSON Guide](https://www.baeldung.com/mongodb-bson) +- [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) diff --git a/persistence-modules/java-mongodb/pom.xml b/persistence-modules/java-mongodb/pom.xml index 9658ef567f..dc4503c95e 100644 --- a/persistence-modules/java-mongodb/pom.xml +++ b/persistence-modules/java-mongodb/pom.xml @@ -22,8 +22,6 @@ ${flapdoodle.version} test - - org.mongodb mongo-java-driver @@ -35,8 +33,8 @@ 1.8 1.8 - 3.4.1 + 3.10.1 1.11 - \ No newline at end of file + diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java new file mode 100644 index 0000000000..0ad3dfae30 --- /dev/null +++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java @@ -0,0 +1,79 @@ +package com.baeldung; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MongoBsonExample +{ + public static void main(String[] args) + { + // + // 4.1 Connect to cluster (default is localhost:27017) + // + + MongoClient mongoClient = MongoClients.create(); + MongoDatabase database = mongoClient.getDatabase("myDB"); + MongoCollection collection = database.getCollection("employees"); + + // + // 4.2 Insert new document + // + + Document employee = new Document() + .append("first_name", "Joe") + .append("last_name", "Smith") + .append("title", "Java Developer") + .append("years_of_service", 3) + .append("skills", Arrays.asList("java", "spring", "mongodb")) + .append("manager", new Document() + .append("first_name", "Sally") + .append("last_name", "Johanson")); + collection.insertOne(employee); + + // + // 4.3 Find documents + // + + + Document query = new Document("last_name", "Smith"); + List results = new ArrayList<>(); + collection.find(query).into(results); + + query = + new Document("$or", Arrays.asList( + new Document("last_name", "Smith"), + new Document("first_name", "Joe"))); + results = new ArrayList<>(); + collection.find(query).into(results); + + // + // 4.4 Update document + // + + query = new Document( + "skills", + new Document( + "$elemMatch", + new Document("$eq", "spring"))); + Document update = new Document( + "$push", + new Document("skills", "security")); + collection.updateMany(query, update); + + // + // 4.5 Delete documents + // + + query = new Document( + "years_of_service", + new Document("$lt", 0)); + collection.deleteMany(query); + } +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/AppIntegrationTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/AppLiveTest.java similarity index 98% rename from persistence-modules/java-mongodb/src/test/java/com/baeldung/AppIntegrationTest.java rename to persistence-modules/java-mongodb/src/test/java/com/baeldung/AppLiveTest.java index 94d1a01492..7692a37d03 100644 --- a/persistence-modules/java-mongodb/src/test/java/com/baeldung/AppIntegrationTest.java +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/AppLiveTest.java @@ -19,7 +19,7 @@ import de.flapdoodle.embedmongo.config.MongodConfig; import de.flapdoodle.embedmongo.distribution.Version; import de.flapdoodle.embedmongo.runtime.Network; -public class AppIntegrationTest { +public class AppLiveTest { private static final String DB_NAME = "myMongoDb"; private MongodExecutable mongodExe; diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/geo/MongoGeospatialLiveTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/geo/MongoGeospatialLiveTest.java new file mode 100644 index 0000000000..6e5a56491b --- /dev/null +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/geo/MongoGeospatialLiveTest.java @@ -0,0 +1,110 @@ +package com.baeldung.geo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.bson.Document; +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.MongoClient; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Indexes; +import com.mongodb.client.model.geojson.Point; +import com.mongodb.client.model.geojson.Polygon; +import com.mongodb.client.model.geojson.Position; + +public class MongoGeospatialLiveTest { + + private MongoClient mongoClient; + private MongoDatabase db; + private MongoCollection collection; + + @Before + public void setup() { + if (mongoClient == null) { + mongoClient = new MongoClient(); + db = mongoClient.getDatabase("myMongoDb"); + collection = db.getCollection("places"); + collection.deleteMany(new Document()); + collection.createIndex(Indexes.geo2dsphere("location")); + collection.insertOne(Document.parse("{'name':'Big Ben','location': {'coordinates':[-0.1268194,51.5007292],'type':'Point'}}")); + collection.insertOne(Document.parse("{'name':'Hyde Park','location': {'coordinates': [[[-0.159381,51.513126],[-0.189615,51.509928],[-0.187373,51.502442], [-0.153019,51.503464],[-0.159381,51.513126]]],'type':'Polygon'}}")); + } + } + + @Test + public void givenNearbyLocation_whenSearchNearby_thenFound() { + Point currentLoc = new Point(new Position(-0.126821, 51.495885)); + FindIterable result = collection.find(Filters.near("location", currentLoc, 1000.0, 10.0)); + + assertNotNull(result.first()); + assertEquals("Big Ben", result.first().get("name")); + } + + @Test + public void givenFarLocation_whenSearchNearby_thenNotFound() { + Point currentLoc = new Point(new Position(-0.5243333, 51.4700223)); + FindIterable result = collection.find(Filters.near("location", currentLoc, 5000.0, 10.0)); + + assertNull(result.first()); + } + + @Test + public void givenNearbyLocation_whenSearchWithinCircleSphere_thenFound() { + double distanceInRad = 5.0 / 6371; + FindIterable result = collection.find(Filters.geoWithinCenterSphere("location", -0.1435083, 51.4990956, distanceInRad)); + + assertNotNull(result.first()); + assertEquals("Big Ben", result.first().get("name")); + } + + @Test + public void givenNearbyLocation_whenSearchWithinBox_thenFound() { + double lowerLeftX = -0.1427638; + double lowerLeftY = 51.4991288; + double upperRightX = -0.1256209; + double upperRightY = 51.5030272; + + FindIterable result = collection.find(Filters.geoWithinBox("location", lowerLeftX, lowerLeftY, upperRightX, upperRightY)); + + assertNotNull(result.first()); + assertEquals("Big Ben", result.first().get("name")); + } + + @Test + public void givenNearbyLocation_whenSearchWithinPolygon_thenFound() { + ArrayList> points = new ArrayList>(); + points.add(Arrays.asList(-0.1439, 51.4952)); // victoria station + points.add(Arrays.asList(-0.1121, 51.4989));// Lambeth North + points.add(Arrays.asList(-0.13, 51.5163));// Tottenham Court Road + points.add(Arrays.asList(-0.1439, 51.4952)); // victoria station + FindIterable result = collection.find(Filters.geoWithinPolygon("location", points)); + + assertNotNull(result.first()); + assertEquals("Big Ben", result.first().get("name")); + } + + @Test + public void givenNearbyLocation_whenSearchUsingIntersect_thenFound() { + ArrayList positions = new ArrayList(); + positions.add(new Position(-0.1439, 51.4952)); + positions.add(new Position(-0.1346, 51.4978)); + positions.add(new Position(-0.2177, 51.5135)); + positions.add(new Position(-0.1439, 51.4952)); + Polygon geometry = new Polygon(positions); + FindIterable result = collection.find(Filters.geoIntersects("location", geometry)); + + assertNotNull(result.first()); + assertEquals("Hyde Park", result.first().get("name")); + } + +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingIntegrationTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingLiveTest.java similarity index 99% rename from persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingIntegrationTest.java rename to persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingLiveTest.java index ffb945e6d4..edd8e22775 100644 --- a/persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingIntegrationTest.java +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/tagging/TaggingLiveTest.java @@ -16,7 +16,7 @@ import org.junit.Test; * @author Donato Rimenti * */ -public class TaggingIntegrationTest { +public class TaggingLiveTest { /** * Object to test. diff --git a/persistence-modules/jnosql/jnosql-artemis/pom.xml b/persistence-modules/jnosql/jnosql-artemis/pom.xml index 8a978fb179..09d6af13df 100644 --- a/persistence-modules/jnosql/jnosql-artemis/pom.xml +++ b/persistence-modules/jnosql/jnosql-artemis/pom.xml @@ -12,11 +12,30 @@ jnosql 1.0-SNAPSHOT - - - 2.4.2 - false - + + + + javax + javaee-web-api + ${javaee-web-api.version} + provided + + + org.jnosql.artemis + artemis-configuration + ${jnosql.version} + + + org.jnosql.artemis + artemis-document + ${jnosql.version} + + + org.jnosql.diana + mongodb-driver + ${jnosql.version} + + ${project.artifactId} @@ -58,31 +77,10 @@ - - - - javax - javaee-web-api - 8.0 - provided - - - - org.jnosql.artemis - artemis-configuration - ${jnosql.version} - - - org.jnosql.artemis - artemis-document - ${jnosql.version} - - - org.jnosql.diana - mongodb-driver - ${jnosql.version} - - - + + 2.4.2 + false + 8.0 + diff --git a/persistence-modules/jnosql/jnosql-diana/pom.xml b/persistence-modules/jnosql/jnosql-diana/pom.xml index 126f0314d9..a4951761d8 100644 --- a/persistence-modules/jnosql/jnosql-diana/pom.xml +++ b/persistence-modules/jnosql/jnosql-diana/pom.xml @@ -12,6 +12,45 @@ 1.0-SNAPSHOT + + + + + org.jnosql.diana + diana-document + ${jnosql.version} + + + org.jnosql.diana + mongodb-driver + ${jnosql.version} + + + + + org.jnosql.diana + diana-column + ${jnosql.version} + + + org.jnosql.diana + cassandra-driver + ${jnosql.version} + + + + + org.jnosql.diana + diana-key-value + ${jnosql.version} + + + org.jnosql.diana + hazelcast-driver + ${jnosql.version} + + + @@ -51,43 +90,4 @@ - - - - - org.jnosql.diana - diana-document - 0.0.5 - - - org.jnosql.diana - mongodb-driver - 0.0.5 - - - - - org.jnosql.diana - diana-column - 0.0.5 - - - org.jnosql.diana - cassandra-driver - 0.0.5 - - - - - org.jnosql.diana - diana-key-value - 0.0.5 - - - org.jnosql.diana - hazelcast-driver - 0.0.5 - - - \ No newline at end of file diff --git a/persistence-modules/jnosql/pom.xml b/persistence-modules/jnosql/pom.xml index 5fb29a3b9c..513a447b91 100644 --- a/persistence-modules/jnosql/pom.xml +++ b/persistence-modules/jnosql/pom.xml @@ -9,15 +9,14 @@ jnosql pom - - 1.8 - 1.8 - 0.0.5 - - jnosql-diana jnosql-artemis + + 1.8 + 1.8 + 0.0.5 + diff --git a/persistence-modules/jpa-hibernate-cascade-type/pom.xml b/persistence-modules/jpa-hibernate-cascade-type/pom.xml new file mode 100644 index 0000000000..a45f297a6b --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/pom.xml @@ -0,0 +1,71 @@ + + + jpa-hibernate-cascade-type + 4.0.0 + 1.0.0-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + com.h2database + h2 + ${h2.version} + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + javax.el + javax.el-api + ${javax.el-api.version} + + + org.glassfish + javax.el + ${org.glassfish.javax.el.version} + + + + + jpa-hibernate-cascade-type + + + src/test/resources + true + + + + + + 5.4.3.Final + 3.12.2 + 6.0.17.Final + 3.0.0 + 3.0.1-b11 + 1.8 + 1.8 + + + \ No newline at end of file diff --git a/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/HibernateUtil.java b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/HibernateUtil.java new file mode 100644 index 0000000000..700c289e38 --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/HibernateUtil.java @@ -0,0 +1,45 @@ +package com.baeldung.cascading; + +import com.baeldung.cascading.domain.Address; +import com.baeldung.cascading.domain.Person; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.service.ServiceRegistry; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + + public static SessionFactory getSessionFactory() { + try { + Properties properties = getProperties(); + Configuration configuration = new Configuration(); + configuration.setProperties(properties); + configuration.addAnnotatedClass(Person.class); + configuration.addAnnotatedClass(Address.class); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(configuration.getProperties()).build(); + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + return sessionFactory; + } catch (IOException e) { + e.printStackTrace(); + } + return sessionFactory; + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource("hibernate.properties"); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} diff --git a/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Address.java b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Address.java new file mode 100644 index 0000000000..a16b0f81b6 --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Address.java @@ -0,0 +1,64 @@ +package com.baeldung.cascading.domain; + +import javax.persistence.*; + +@Entity +public class Address { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String street; + private int houseNumber; + private String city; + private int zipCode; + @ManyToOne(fetch = FetchType.LAZY) + private Person person; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public String getStreet() { + return street; + } + + public int getHouseNumber() { + return houseNumber; + } + + public void setHouseNumber(int houseNumber) { + this.houseNumber = houseNumber; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public int getZipCode() { + return zipCode; + } + + public void setZipCode(int zipCode) { + this.zipCode = zipCode; + } + + public void setStreet(String street) { + this.street = street; + } +} diff --git a/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Person.java b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Person.java new file mode 100644 index 0000000000..9ca61323b3 --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/src/main/java/com/baeldung/cascading/domain/Person.java @@ -0,0 +1,38 @@ +package com.baeldung.cascading.domain; + +import javax.persistence.*; +import java.util.List; + +@Entity +public class Person { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String name; + @OneToMany(mappedBy = "person", cascade = CascadeType.ALL) + private List
addresses; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List
getAddresses() { + return addresses; + } + + public void setAddresses(List
addresses) { + this.addresses = addresses; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/jpa-hibernate-cascade-type/src/test/java/com/baeldung/cascading/CasCadeTypeUnitTest.java b/persistence-modules/jpa-hibernate-cascade-type/src/test/java/com/baeldung/cascading/CasCadeTypeUnitTest.java new file mode 100644 index 0000000000..a196bdac12 --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/src/test/java/com/baeldung/cascading/CasCadeTypeUnitTest.java @@ -0,0 +1,169 @@ +package com.baeldung.cascading; + +import com.baeldung.cascading.domain.Address; +import com.baeldung.cascading.domain.Person; +import org.assertj.core.api.Assertions; +import org.hibernate.*; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Arrays; + +public class CasCadeTypeUnitTest { + private static SessionFactory sessionFactory; + private Session session; + private Transaction transaction; + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + } + + @After + public void tearDown() { + transaction.rollback(); + session.close(); + } + + @Test + public void testPersist() { + Person person = new Person(); + Address address = new Address(); + address.setPerson(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + session.clear(); + } + + @Test + public void testMerge() { + int addressId; + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + addressId = address.getId(); + session.clear(); + + Address savedAddressEntity = session.find(Address.class, addressId); + Person savedPersonEntity = savedAddressEntity.getPerson(); + savedPersonEntity.setName("devender kumar"); + savedAddressEntity.setHouseNumber(24); + session.merge(savedPersonEntity); + session.flush(); + } + + @Test + public void testRemove() { + int personId; + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + personId = person.getId(); + session.clear(); + + Person savedPersonEntity = session.find(Person.class, personId); + session.remove(savedPersonEntity); + session.flush(); + } + + @Test + public void testDetach() { + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + Assertions.assertThat(session.contains(person)).isTrue(); + Assertions.assertThat(session.contains(address)).isTrue(); + + session.detach(person); + Assertions.assertThat(session.contains(person)).isFalse(); + Assertions.assertThat(session.contains(address)).isFalse(); + } + + @Test + public void testLock() { + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + Assertions.assertThat(session.contains(person)).isTrue(); + Assertions.assertThat(session.contains(address)).isTrue(); + + session.detach(person); + Assertions.assertThat(session.contains(person)).isFalse(); + Assertions.assertThat(session.contains(address)).isFalse(); + session.unwrap(Session.class) + .buildLockRequest(new LockOptions(LockMode.NONE)) + .lock(person); + + Assertions.assertThat(session.contains(person)).isTrue(); + Assertions.assertThat(session.contains(address)).isTrue(); + } + + @Test + public void testRefresh() { + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.persist(person); + session.flush(); + person.setName("Devender Kumar"); + address.setHouseNumber(24); + session.refresh(person); + Assertions.assertThat(person.getName()).isEqualTo("devender"); + Assertions.assertThat(address.getHouseNumber()).isEqualTo(23); + } + + @Test + public void testReplicate() { + Person person = buildPerson("devender"); + person.setId(2); + Address address = buildAddress(person); + address.setId(2); + person.setAddresses(Arrays.asList(address)); + session.unwrap(Session.class).replicate(person, ReplicationMode.OVERWRITE); + session.flush(); + Assertions.assertThat(person.getId()).isEqualTo(2); + Assertions.assertThat(address.getId()).isEqualTo(2); + } + + @Test + public void testSaveOrUpdate() { + Person person = buildPerson("devender"); + Address address = buildAddress(person); + person.setAddresses(Arrays.asList(address)); + session.saveOrUpdate(person); + session.flush(); + } + + private Address buildAddress(Person person) { + Address address = new Address(); + address.setCity("Berlin"); + address.setHouseNumber(23); + address.setStreet("Zeughofstraße"); + address.setZipCode(123001); + address.setPerson(person); + return address; + } + + private Person buildPerson(String name) { + Person person = new Person(); + person.setName(name); + return person; + } +} diff --git a/persistence-modules/jpa-hibernate-cascade-type/src/test/resources/hibernate.properties b/persistence-modules/jpa-hibernate-cascade-type/src/test/resources/hibernate.properties new file mode 100644 index 0000000000..c22da2496b --- /dev/null +++ b/persistence-modules/jpa-hibernate-cascade-type/src/test/resources/hibernate.properties @@ -0,0 +1,10 @@ +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop + diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml new file mode 100644 index 0000000000..390bcc9d51 --- /dev/null +++ b/persistence-modules/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + persistence-modules + persistence-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + activejdbc + apache-cayenne + core-java-persistence + deltaspike + elasticsearch + flyway + hbase + hibernate5 + hibernate-ogm + hibernate-mapping + influxdb + java-cassandra + java-cockroachdb + java-jdbi + java-jpa + java-mongodb + jnosql + liquibase + orientdb + querydsl + redis + solr + spring-boot-persistence-h2 + 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 + spring-persistence-simple + jpa-hibernate-cascade-type + + diff --git a/persistence-modules/querydsl/pom.xml b/persistence-modules/querydsl/pom.xml index d3bf1b1fb7..4d4347e909 100644 --- a/persistence-modules/querydsl/pom.xml +++ b/persistence-modules/querydsl/pom.xml @@ -5,8 +5,8 @@ com.baeldung querydsl 0.1-SNAPSHOT - jar querydsl + jar http://maven.apache.org diff --git a/persistence-modules/solr/pom.xml b/persistence-modules/solr/pom.xml index 49f2f85856..1c14c06315 100644 --- a/persistence-modules/solr/pom.xml +++ b/persistence-modules/solr/pom.xml @@ -4,8 +4,8 @@ com.baeldung solr 0.0.1-SNAPSHOT - jar solr + jar com.baeldung diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/.gitignore b/persistence-modules/spring-boot-persistence-h2/.gitignore similarity index 100% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/.gitignore rename to persistence-modules/spring-boot-persistence-h2/.gitignore diff --git a/persistence-modules/spring-boot-h2/README.md b/persistence-modules/spring-boot-persistence-h2/README.md similarity index 67% rename from persistence-modules/spring-boot-h2/README.md rename to persistence-modules/spring-boot-persistence-h2/README.md index af5f395440..377b7c8939 100644 --- a/persistence-modules/spring-boot-h2/README.md +++ b/persistence-modules/spring-boot-persistence-h2/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Access the Same In-Memory H2 Database in Multiple Spring Boot Applications](https://www.baeldung.com/spring-boot-access-h2-database-multiple-apps) +- [Spring Boot With H2 Database](https://www.baeldung.com/spring-boot-h2-database) \ No newline at end of file diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml similarity index 87% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml rename to persistence-modules/spring-boot-persistence-h2/pom.xml index 6ebc75de8d..4c8073ddb4 100644 --- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml +++ b/persistence-modules/spring-boot-persistence-h2/pom.xml @@ -8,30 +8,20 @@ 0.0.1-SNAPSHOT spring-boot-h2-database jar - 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 - - UTF-8 - UTF-8 - 1.8 - - com.baeldung.h2db.demo.server.SpringBootApp - - org.springframework.boot spring-boot-starter-data-jpa - com.h2database h2 @@ -51,4 +41,14 @@ + + + UTF-8 + UTF-8 + 1.8 + + com.baeldung.h2db.demo.server.SpringBootApp + 2.0.4.RELEASE + + diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java similarity index 100% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java similarity index 100% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java similarity index 100% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java new file mode 100644 index 0000000000..378093cfa9 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java @@ -0,0 +1,12 @@ +package com.baeldung.h2db.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootH2Application { + + public static void main(String... args) { + SpringApplication.run(SpringBootH2Application.class, args); + } +} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java new file mode 100644 index 0000000000..35e496e910 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.h2db.springboot.daos; + + + + +import com.baeldung.h2db.springboot.models.User; +import org.springframework.data.repository.CrudRepository; + +public interface UserRepository extends CrudRepository { +} diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java new file mode 100644 index 0000000000..fa3c01c035 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java @@ -0,0 +1,54 @@ +package com.baeldung.h2db.springboot.models; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Table(name = "users") +@Entity +public class User { + + @Id + @GeneratedValue + private int id; + + private String firstName; + + private String lastName; + + public User() { } + + public int getId() { + return id; + } + + public void setId(int 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 "User{" + + "id=" + id + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } +} diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties similarity index 80% rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties rename to persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties index 5e425a3550..109b389b58 100644 --- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties @@ -2,7 +2,7 @@ spring.datasource.url=jdbc:h2:mem:mydb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop spring.h2.console.enabled=true spring.h2.console.path=/h2-console debug=true \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql new file mode 100644 index 0000000000..2d7b446005 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS billionaires; + +CREATE TABLE billionaires ( + id INT AUTO_INCREMENT PRIMARY KEY, + first_name VARCHAR(250) NOT NULL, + last_name VARCHAR(250) NOT NULL, + career VARCHAR(250) DEFAULT NULL +); + +INSERT INTO billionaires (first_name, last_name, career) VALUES +('Aliko', 'Dangote', 'Billionaire Industrialist'), +('Bill', 'Gates', 'Billionaire Tech Entrepreneur'), +('Folrunsho', 'Alakija', 'Billionaire Oil Magnate'); \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java new file mode 100644 index 0000000000..aecc63c599 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung; + +import com.baeldung.h2db.springboot.SpringBootH2Application; +import com.baeldung.h2db.springboot.daos.UserRepository; +import com.baeldung.h2db.springboot.models.User; +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.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringBootH2Application.class) +public class SpringBootH2IntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Test + public void contextLoads() { } + + @Test + public void givenUserProfile_whenAddUser_thenCreateNewUser() { + User user = new User(); + user.setFirstName("John"); + user.setLastName("Doe"); + userRepository.save(user); + List users = (List) userRepository.findAll(); + assertFalse(users.isEmpty()); + + String firstName = "Aliko"; + String lastName = "Dangote"; + User user1 = userRepository.findById(users.get(0).getId()).get(); + user1.setLastName(lastName); + user1.setFirstName(firstName); + userRepository.save(user1); + + user = userRepository.findById(user.getId()).get(); + assertEquals(user.getFirstName(), firstName); + assertEquals(user.getLastName(), lastName); + + userRepository.deleteById(user.getId()); + assertTrue( ((List) userRepository.findAll()).isEmpty()); + } + +} diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..cf964b5011 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} 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/persistence-modules/spring-boot-persistence-mongodb/pom.xml b/persistence-modules/spring-boot-persistence-mongodb/pom.xml index fc267eedf6..dae5efa6d0 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/pom.xml +++ b/persistence-modules/spring-boot-persistence-mongodb/pom.xml @@ -3,6 +3,10 @@ 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-boot-persistence-mongodb + spring-boot-persistence-mongodb + war + This is simple boot application for Spring boot persistence mongodb test parent-boot-2 @@ -11,21 +15,25 @@ ../../parent-boot-2 - spring-boot-persistence-mongodb - war - spring-boot-persistence-mongodb - This is simple boot application for Spring boot persistence mongodb test - org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-thymeleaf + org.springframework.boot spring-boot-starter-data-mongodb + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + org.junit.jupiter @@ -103,4 +111,4 @@ - \ No newline at end of file + diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/daos/PhotoRepository.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/daos/PhotoRepository.java new file mode 100644 index 0000000000..d38e11c055 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/daos/PhotoRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.mongodb.daos; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.mongodb.models.Photo; + +public interface PhotoRepository extends MongoRepository { + +} 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)); + } } diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Photo.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Photo.java new file mode 100644 index 0000000000..13f1a3cd19 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Photo.java @@ -0,0 +1,51 @@ +package com.baeldung.mongodb.models; + +import org.bson.types.Binary; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection = "photos") +public class Photo { + + @Id + private String id; + + private String title; + + private Binary image; + + public Photo(String title) { + super(); + this.title = title; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Binary getImage() { + return image; + } + + public void setImage(Binary image) { + this.image = image; + } + + @Override + public String toString() { + return "Photo [id=" + id + ", title=" + title + ", image=" + image + "]"; + } + +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Video.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Video.java new file mode 100644 index 0000000000..617f0cdbfd --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/models/Video.java @@ -0,0 +1,39 @@ +package com.baeldung.mongodb.models; + +import java.io.InputStream; + +public class Video { + private String title; + private InputStream stream; + + public Video() { + super(); + } + + public Video(String title) { + super(); + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public InputStream getStream() { + return stream; + } + + public void setStream(InputStream stream) { + this.stream = stream; + } + + @Override + public String toString() { + return "Video [title=" + title + "]"; + } + +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/PhotoService.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/PhotoService.java new file mode 100644 index 0000000000..685d67c40f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/PhotoService.java @@ -0,0 +1,38 @@ +package com.baeldung.mongodb.services; + +import java.io.IOException; +import java.util.Optional; + +import org.bson.BsonBinarySubType; +import org.bson.types.Binary; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.mongodb.daos.PhotoRepository; +import com.baeldung.mongodb.models.Photo; + +@Service +public class PhotoService { + + @Autowired + private PhotoRepository photoRepo; + + public Photo getPhoto(String id) { + Optional result = photoRepo.findById(id); + return result.isPresent() ? result.get() : null; + } + + public String addPhoto(String title, MultipartFile file) { + String id = null; + try { + Photo photo = new Photo(title); + photo.setImage(new Binary(BsonBinarySubType.BINARY, file.getBytes())); + photo = photoRepo.insert(photo); + id = photo.getId(); + } catch (IOException e) { + return null; + } + return id; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/VideoService.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/VideoService.java new file mode 100644 index 0000000000..dea6540973 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/services/VideoService.java @@ -0,0 +1,56 @@ +package com.baeldung.mongodb.services; + +import java.io.IOException; + +import org.bson.types.ObjectId; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.gridfs.GridFsOperations; +import org.springframework.data.mongodb.gridfs.GridFsTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.mongodb.models.Video; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import com.mongodb.client.gridfs.model.GridFSFile; + +@Service +public class VideoService { + + @Autowired + private GridFsTemplate gridFsTemplate; + + @Autowired + private GridFsOperations operations; + + public Video getVideo(String id) { + Video video = null; + GridFSFile file = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(id))); + if (file != null) { + video = new Video(); + video.setTitle(file.getMetadata().get("title").toString()); + try { + video.setStream(operations.getResource(file).getInputStream()); + } catch (IOException e) { + return null; + } + } + return video; + } + + public String addVideo(String title, MultipartFile file) { + DBObject metaData = new BasicDBObject(); + metaData.put("type", "video"); + metaData.put("title", title); + ObjectId id; + try { + id = gridFsTemplate.store(file.getInputStream(), file.getName(), file.getContentType(), metaData); + } catch (IOException e) { + return null; + } + return id.toString(); + } + +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/PhotoController.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/PhotoController.java new file mode 100644 index 0000000000..fffb6ec320 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/PhotoController.java @@ -0,0 +1,50 @@ +package com.baeldung.mongodb.web; + +import java.util.Base64; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +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.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.mongodb.models.Photo; +import com.baeldung.mongodb.services.PhotoService; + +@Controller +public class PhotoController { + + @Autowired + private PhotoService photoService; + + @GetMapping("/photos/{id}") + public String getPhoto(@PathVariable String id, Model model) { + Photo photo = photoService.getPhoto(id); + if (photo != null) { + model.addAttribute("title", photo.getTitle()); + model.addAttribute("image", Base64.getEncoder().encodeToString(photo.getImage().getData())); + return "photos"; + } + model.addAttribute("message", "Photo not found"); + return "index"; + } + + @GetMapping("/photos/upload") + public String uploadPhoto(Model model) { + model.addAttribute("message", "hello"); + return "uploadPhoto"; + } + + @PostMapping("/photos/add") + public String addPhoto(@RequestParam("title") String title, @RequestParam("image") MultipartFile image, Model model) { + String id = photoService.addPhoto(title, image); + if (id == null) { + model.addAttribute("message", "Error Occurred"); + return "index"; + } + return "redirect:/photos/" + id; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/VideoController.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/VideoController.java new file mode 100644 index 0000000000..e5fda0cc64 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/web/VideoController.java @@ -0,0 +1,67 @@ +package com.baeldung.mongodb.web; + +import java.io.IOException; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.FileCopyUtils; +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.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.mongodb.models.Video; +import com.baeldung.mongodb.services.VideoService; + +@Controller +public class VideoController { + + @Autowired + private VideoService videoService; + + @GetMapping("/videos/{id}") + public String getVideo(@PathVariable String id, Model model) { + Video video = videoService.getVideo(id); + if (video != null) { + model.addAttribute("title", video.getTitle()); + model.addAttribute("url", "/videos/stream/" + id); + return "videos"; + } + model.addAttribute("message", "Video not found"); + return "index"; + } + + @GetMapping("/videos/stream/{id}") + public void streamVideo(@PathVariable String id, HttpServletResponse response) { + Video video = videoService.getVideo(id); + if (video != null) { + try { + FileCopyUtils.copy(video.getStream(), response.getOutputStream()); + } catch (IOException e) { + response.setStatus(500); + } + } else { + response.setStatus(404); + } + } + + @GetMapping("/videos/upload") + public String uploadVideo(Model model) { + model.addAttribute("message", "hello"); + return "uploadVideo"; + } + + @PostMapping("/videos/add") + public String addVideo(@RequestParam("title") String title, @RequestParam("file") MultipartFile file, Model model) { + String id = videoService.addVideo(title, file); + if (id == null) { + model.addAttribute("message", "Error Occurred"); + return "index"; + } + return "redirect:/videos/" + id; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties index 5b1b8000d0..6548f2b28a 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/application.properties @@ -1,8 +1,13 @@ spring.application.name=spring-boot-persistence -server.port=${PORT:0} +server.port=8082 #spring boot mongodb spring.data.mongodb.host=localhost spring.data.mongodb.port=27017 spring.data.mongodb.database=springboot-mongo +spring.thymeleaf.cache=false + +spring.servlet.multipart.max-file-size=256MB +spring.servlet.multipart.max-request-size=256MB +spring.servlet.multipart.enabled=true \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/index.html b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/index.html new file mode 100644 index 0000000000..f99e9caa8b --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/index.html @@ -0,0 +1,14 @@ + + + +Upload Files MongoDB + + +

Home Page

+
Message
+
+ Upload new Photo +

+ Upload new Video + + diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/photos.html b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/photos.html new file mode 100644 index 0000000000..b5d56d020a --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/photos.html @@ -0,0 +1,10 @@ + + +

View Photo

+ Title: name +
+ sample +

+ Back to home page + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadPhoto.html b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadPhoto.html new file mode 100644 index 0000000000..6d51c06d8f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadPhoto.html @@ -0,0 +1,15 @@ + + + +

Upload new Photo

+
+ Title: +
+ Image: +
+
+ +
+ + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadVideo.html b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadVideo.html new file mode 100644 index 0000000000..ebc29d98e2 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/uploadVideo.html @@ -0,0 +1,15 @@ + + + +

Upload new Video

+
+ Title: +
+ Video: +
+
+ +
+ + + \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/videos.html b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/videos.html new file mode 100644 index 0000000000..b0ee0fc577 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/templates/videos.html @@ -0,0 +1,15 @@ + + +

View Video

+ Title: title +
+
+ + + +

+ Back to home page + + \ No newline at end of file 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 90% 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 index 39127f62e9..954bae3684 100644 --- 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 @@ -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 { diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index 8988fb4ebd..709f505ea9 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -2,6 +2,10 @@ - [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) +- [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) +- [Spring Boot with Hibernate](https://www.baeldung.com/spring-boot-hibernate) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index 0ea42b1cb7..e283759c75 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -1,20 +1,18 @@ - - 4.0.0 - com.baeldung + + 4.0.0 spring-boot-persistence 0.1.0 - spring-boot-persistence - + spring-boot-persistence + parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 - + org.springframework.boot @@ -27,6 +25,12 @@ org.springframework.boot spring-boot-starter-data-jpa + + + com.zaxxer + HikariCP + + org.springframework.boot @@ -35,42 +39,35 @@ org.mockito mockito-core - ${mockito.version} test com.h2database h2 - ${h2database.version} runtime - + org.apache.tomcat tomcat-jdbc - ${tomcat-jdbc.version} mysql mysql-connector-java - ${mysql-connector-java.version} + + + javax.validation + validation-api + ${validation-api.version} - - UTF-8 - 1.8 - 8.0.12 - 9.0.10 - 1.4.197 - 2.23.0 - - + spring-boot-persistence - - src/main/resources - true - + + src/main/resources + true + @@ -79,4 +76,13 @@ + + + UTF-8 + 8.0.12 + 9.0.10 + 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/boot/config/H2JpaConfig.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java index ef90714347..c5c77be56f 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java @@ -1,13 +1,9 @@ package com.baeldung.boot.config; -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -17,10 +13,17 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.annotation.EnableTransactionManagement; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; + @Configuration -@EnableJpaRepositories(basePackages = { "org.baeldung.boot.repository", "org.baeldung.repository" }) +@EnableJpaRepositories(basePackages = { "com.baeldung.boot.repository", "com.baeldung.repository" }) @PropertySource("classpath:persistence-generic-entity.properties") @EnableTransactionManagement +@Profile("default") //only required to allow H2JpaConfig and H2TestProfileJPAConfig to coexist in same project + //this demo project is showcasing several ways to achieve the same end, and class-level + //Profile annotations are only necessary because the different techniques are sharing a project public class H2JpaConfig { @Autowired @@ -41,7 +44,7 @@ public class H2JpaConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.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/main/java/com/baeldung/boot/domain/Car.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java new file mode 100644 index 0000000000..736c12fb07 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java @@ -0,0 +1,48 @@ +package com.baeldung.boot.domain; + +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; + + public 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/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/org/baeldung/boot/domain/GenericEntity.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java similarity index 95% rename from persistence-modules/spring-boot-persistence/src/main/java/org/baeldung/boot/domain/GenericEntity.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java index f1c936e432..a2a676200a 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/org/baeldung/boot/domain/GenericEntity.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/GenericEntity.java @@ -1,4 +1,4 @@ -package org.baeldung.boot.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/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/boot/repository/CarRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/CarRepository.java new file mode 100644 index 0000000000..0176b14169 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/CarRepository.java @@ -0,0 +1,26 @@ +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 + */ +@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/main/java/org/baeldung/boot/repository/GenericEntityRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java similarity index 63% rename from persistence-modules/spring-boot-persistence/src/main/java/org/baeldung/boot/repository/GenericEntityRepository.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java index d897e17afe..bbc2865856 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/org/baeldung/boot/repository/GenericEntityRepository.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java @@ -1,7 +1,8 @@ -package org.baeldung.boot.repository; +package com.baeldung.boot.repository; -import org.baeldung.boot.domain.GenericEntity; import org.springframework.data.jpa.repository.JpaRepository; +import com.baeldung.boot.domain.GenericEntity; + public interface GenericEntityRepository extends JpaRepository { } 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/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); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java new file mode 100644 index 0000000000..e1f67c0185 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java @@ -0,0 +1,27 @@ +package com.baeldung.springbootdatasourceconfig.application; + +import com.baeldung.springbootdatasourceconfig.application.entities.User; +import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository; +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 + public CommandLineRunner run(UserRepository userRepository) throws Exception { + return (String[] args) -> { + User user1 = new User("John", "john@domain.com"); + User user2 = new User("Julie", "julie@domain.com"); + userRepository.save(user1); + userRepository.save(user2); + userRepository.findAll().forEach(user -> System.out.println(user.getName())); + }; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java new file mode 100644 index 0000000000..9ef9b77aed --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java @@ -0,0 +1,20 @@ +package com.baeldung.springbootdatasourceconfig.application.datasources; + +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 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/springbootdatasourceconfig/application/entities/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java new file mode 100644 index 0000000000..518a11701f --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java @@ -0,0 +1,46 @@ +package com.baeldung.springbootdatasourceconfig.application.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + private String name; + private String email; + + public User(){} + + public User(String name, String email) { + this.name = name; + this.email = email; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public String toString() { + return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java new file mode 100644 index 0000000000..27929ead44 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.springbootdatasourceconfig.application.repositories; + +import com.baeldung.springbootdatasourceconfig.application.entities.User; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends CrudRepository {} 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/java/com/baeldung/springboothsqldb/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/Application.java new file mode 100644 index 0000000000..c5a5c291c6 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.springboothsqldb.application; + +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-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/controllers/CustomerController.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/controllers/CustomerController.java new file mode 100644 index 0000000000..8229a1d1c0 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/controllers/CustomerController.java @@ -0,0 +1,33 @@ +package com.baeldung.springboothsqldb.application.controllers; + +import com.baeldung.springboothsqldb.application.entities.Customer; +import com.baeldung.springboothsqldb.application.repositories.CustomerRepository; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +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.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CustomerController { + + private final CustomerRepository customerRepository; + + @Autowired + public CustomerController(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + @PostMapping("/customers") + public Customer addCustomer(@RequestBody Customer customer) { + customerRepository.save(customer); + return customer; + } + + @GetMapping("/customers") + public List getCustomers() { + return (List) customerRepository.findAll(); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/entities/Customer.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/entities/Customer.java new file mode 100644 index 0000000000..636a80e272 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/entities/Customer.java @@ -0,0 +1,55 @@ +package com.baeldung.springboothsqldb.application.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "customers") +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + private String email; + + public Customer() {} + + public Customer(String name, String email) { + this.name = name; + this.email = email; + } + + public void setId(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getEmail() { + return email; + } + + @Override + public String toString() { + return "Customer{" + "id=" + id + ", name=" + name + ", email=" + email + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/repositories/CustomerRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/repositories/CustomerRepository.java new file mode 100644 index 0000000000..a81aa62c43 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothsqldb/application/repositories/CustomerRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.springboothsqldb.application.repositories; + +import com.baeldung.springboothsqldb.application.entities.Customer; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CustomerRepository extends CrudRepository {} 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 303ce33c25..7b5a467a2b 100644 --- a/persistence-modules/spring-boot-persistence/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence/src/main/resources/application.properties @@ -1,16 +1,11 @@ -spring.datasource.tomcat.initial-size=15 -spring.datasource.tomcat.max-wait=20000 -spring.datasource.tomcat.max-active=50 -spring.datasource.tomcat.max-idle=15 -spring.datasource.tomcat.min-idle=8 -spring.datasource.tomcat.default-auto-commit=true -spring.datasource.url=jdbc:h2:mem:test -spring.datasource.username=root -spring.datasource.password= -spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.driver-class-name = org.hsqldb.jdbc.JDBCDriver +spring.datasource.url = jdbc:hsqldb:mem:test;DB_CLOSE_DELAY=-1 +spring.datasource.username = sa +spring.datasource.password = +spring.jpa.hibernate.ddl-auto = create -spring.jpa.show-sql=false -spring.jpa.hibernate.ddl-auto=update -spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect -spring.jpa.properties.hibernate.id.new_generator_mappings=false +# 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/main/resources/templates/index.html b/persistence-modules/spring-boot-persistence/src/main/resources/templates/index.html index 2634e10380..344d4e59f5 100644 --- a/persistence-modules/spring-boot-persistence/src/main/resources/templates/index.html +++ b/persistence-modules/spring-boot-persistence/src/main/resources/templates/index.html @@ -40,4 +40,4 @@ - \ No newline at end of file + 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 6479e90113..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 @@ -3,19 +3,21 @@ package com.baeldung; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import org.baeldung.boot.domain.GenericEntity; -import org.baeldung.boot.repository.GenericEntityRepository; 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; +import com.baeldung.boot.Application; import com.baeldung.boot.config.H2JpaConfig; +import com.baeldung.boot.domain.GenericEntity; +import com.baeldung.boot.repository.GenericEntityRepository; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = { Application.class, H2JpaConfig.class }) public class SpringBootH2IntegrationTest { + @Autowired private GenericEntityRepository genericEntityRepository; @@ -23,7 +25,9 @@ public class SpringBootH2IntegrationTest { public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() { GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test")); GenericEntity foundEntity = genericEntityRepository.findById(genericEntity.getId()).orElse(null); + assertNotNull(foundEntity); assertEquals(genericEntity.getValue(), foundEntity.getValue()); } + } \ No newline at end of file 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 eef9ebe953..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 @@ -3,14 +3,16 @@ package com.baeldung; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import org.baeldung.boot.domain.GenericEntity; -import org.baeldung.boot.repository.GenericEntityRepository; 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.boot.Application; +import com.baeldung.boot.domain.GenericEntity; +import com.baeldung.boot.repository.GenericEntityRepository; + @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringBootJPAIntegrationTest { 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 4c68f1d4a0..d7bb44e133 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 @@ -1,11 +1,9 @@ package com.baeldung; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.baeldung.boot.domain.GenericEntity; -import org.baeldung.boot.repository.GenericEntityRepository; -import org.baeldung.config.H2TestProfileJPAConfig; +import com.baeldung.boot.Application; +import com.baeldung.boot.domain.GenericEntity; +import com.baeldung.boot.repository.GenericEntityRepository; +import com.baeldung.config.H2TestProfileJPAConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -13,6 +11,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + @RunWith(SpringRunner.class) @SpringBootTest(classes = { Application.class, H2TestProfileJPAConfig.class }) @ActiveProfiles("test") 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/UserRepositoryMultipleSqlFilesIntTest.java similarity index 66% 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/UserRepositoryMultipleSqlFilesIntTest.java index af5abc22d7..f1f6e85d8c 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/UserRepositoryMultipleSqlFilesIntTest.java @@ -1,12 +1,15 @@ -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.ActiveProfiles; 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; @@ -16,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; @@ -24,7 +28,7 @@ public class UserRepositoryIntegrationTest { public void givenTwoImportFilesWhenFindAllShouldReturnSixUsers() { Collection users = userRepository.findAll(); - assertThat(users.size()).isEqualTo(9); + assertThat(users.size()).isEqualTo(6); } } diff --git a/persistence-modules/spring-boot-persistence/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java similarity index 82% rename from persistence-modules/spring-boot-persistence/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java index 7f962e1417..f73000a10e 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java @@ -1,9 +1,4 @@ -package org.baeldung.config; - -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; +package com.baeldung.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -17,9 +12,16 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.annotation.EnableTransactionManagement; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; + @Configuration -@EnableJpaRepositories(basePackages = { "org.baeldung.repository", "org.baeldung.boot.repository" }) +@EnableJpaRepositories(basePackages = { "com.baeldung.repository", "com.baeldung.boot.repository" }) @EnableTransactionManagement +@Profile("test") //only required to allow H2JpaConfig and H2TestProfileJPAConfig to coexist in same project + //this demo project is showcasing several ways to achieve the same end, and class-level + //Profile annotations are only necessary because the different techniques are sharing a project public class H2TestProfileJPAConfig { @Autowired @@ -41,7 +43,7 @@ public class H2TestProfileJPAConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.baeldung.domain", "org.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/application/tests/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..e9824fce44 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java @@ -0,0 +1,31 @@ +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; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class UserRepositoryIntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Test + public void whenCalledSave_thenCorrectNumberOfUsers() { + 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/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..655a852001 --- /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 whenApplicationStarts_thenHibernateCreatesInitialRecords() { + List books = bookService.list(); + + Assert.assertEquals(books.size(), 3); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerUnitTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerUnitTest.java new file mode 100644 index 0000000000..33891e3d43 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.springboothsqldb.application.tests; + +import com.baeldung.springboothsqldb.application.entities.Customer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.nio.charset.Charset; +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.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class CustomerControllerUnitTest { + + private static MediaType MEDIA_TYPE_JSON; + + @Autowired + private MockMvc mockMvc; + + @Before + public void setUpJsonMediaType() { + MEDIA_TYPE_JSON = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); + + } + + @Test + public void whenPostHttpRequesttoCustomers_thenStatusOK() throws Exception { + Customer customer = new Customer("John", "john@domain.com"); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false); + ObjectWriter objectWriter = mapper.writer().withDefaultPrettyPrinter(); + String requestJson = objectWriter.writeValueAsString(customer); + + this.mockMvc + .perform(MockMvcRequestBuilders.post("/customers") + .contentType(MEDIA_TYPE_JSON) + .content(requestJson) + ) + + .andExpect(MockMvcResultMatchers.status().isOk()); + } + + @Test + public void whenGetHttpRequesttoCustomers_thenStatusOK() throws Exception { + this.mockMvc + .perform(MockMvcRequestBuilders.get("/customers")) + + .andExpect(MockMvcResultMatchers.content().contentType(MEDIA_TYPE_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); + } +} 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..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 @@ -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 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 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 diff --git a/persistence-modules/spring-data-cassandra-reactive/pom.xml b/persistence-modules/spring-data-cassandra-reactive/pom.xml index 5303f9a53a..288f842201 100644 --- a/persistence-modules/spring-data-cassandra-reactive/pom.xml +++ b/persistence-modules/spring-data-cassandra-reactive/pom.xml @@ -3,13 +3,11 @@ 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 spring-data-cassandra-reactive 0.0.1-SNAPSHOT - jar - spring-data-cassandra-reactive + jar Spring Data Cassandra reactive @@ -19,18 +17,11 @@ ../../parent-boot-2 - - UTF-8 - UTF-8 - - 1.8 - - org.springframework.data spring-data-cassandra - 2.1.2.RELEASE + ${spring-data-cassandra.version} io.projectreactor @@ -55,7 +46,21 @@ reactor-test test + + org.cassandraunit + cassandra-unit-spring + ${cassandra-unit-spring.version} + test + + + + UTF-8 + UTF-8 + + 2.1.2.RELEASE + 3.11.2.0 + diff --git a/persistence-modules/spring-data-cassandra-reactive/src/test/java/com/baeldung/cassandra/reactive/ReactiveEmployeeRepositoryIntegrationTest.java b/persistence-modules/spring-data-cassandra-reactive/src/test/java/com/baeldung/cassandra/reactive/ReactiveEmployeeRepositoryIntegrationTest.java index ad726fe969..ae314db5e7 100644 --- a/persistence-modules/spring-data-cassandra-reactive/src/test/java/com/baeldung/cassandra/reactive/ReactiveEmployeeRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-cassandra-reactive/src/test/java/com/baeldung/cassandra/reactive/ReactiveEmployeeRepositoryIntegrationTest.java @@ -1,13 +1,23 @@ package com.baeldung.cassandra.reactive; -import com.baeldung.cassandra.reactive.model.Employee; -import com.baeldung.cassandra.reactive.repository.EmployeeRepository; +import org.cassandraunit.spring.CassandraDataSet; +import org.cassandraunit.spring.CassandraUnitDependencyInjectionTestExecutionListener; +import org.cassandraunit.spring.CassandraUnitTestExecutionListener; +import org.cassandraunit.spring.EmbeddedCassandra; 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.TestExecutionListeners; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; +import org.springframework.test.context.support.DirtiesContextTestExecutionListener; +import org.springframework.test.context.web.ServletTestExecutionListener; + +import com.baeldung.cassandra.reactive.model.Employee; +import com.baeldung.cassandra.reactive.repository.EmployeeRepository; + import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -15,6 +25,15 @@ import reactor.test.StepVerifier; @RunWith(SpringRunner.class) @SpringBootTest +@TestExecutionListeners(listeners = { + CassandraUnitDependencyInjectionTestExecutionListener.class, + CassandraUnitTestExecutionListener.class, + ServletTestExecutionListener.class, + DependencyInjectionTestExecutionListener.class, + DirtiesContextTestExecutionListener.class +}) +@EmbeddedCassandra(timeout = 60000, configuration = "cassandra-server.yaml") +@CassandraDataSet(value = {"cassandra-init.cql"}, keyspace = "practice") public class ReactiveEmployeeRepositoryIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-init.cql b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-init.cql new file mode 100644 index 0000000000..b28fda5320 --- /dev/null +++ b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-init.cql @@ -0,0 +1,7 @@ +CREATE TABLE employee( + id int PRIMARY KEY, + name text, + address text, + email text, + age int +); \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-server.yaml b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-server.yaml new file mode 100644 index 0000000000..af3fb21e54 --- /dev/null +++ b/persistence-modules/spring-data-cassandra-reactive/src/test/resources/cassandra-server.yaml @@ -0,0 +1,590 @@ +# Cassandra storage config YAML + +# NOTE: +# See http://wiki.apache.org/cassandra/StorageConfiguration for +# full explanations of configuration directives +# /NOTE + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'Test Cluster' + +# You should always specify InitialToken when setting up a production +# cluster for the first time, and often when adding capacity later. +# The principle is that each node should be given an equal slice of +# the token ring; see http://wiki.apache.org/cassandra/Operations +# for more details. +# +# If blank, Cassandra will request a token bisecting the range of +# the heaviest-loaded existing node. If there is no load information +# available, such as is the case with a new cluster, it will pick +# a random token, which will lead to hot spots. +#initial_token: + +# See http://wiki.apache.org/cassandra/HintedHandoff +hinted_handoff_enabled: true +# this defines the maximum amount of time a dead host will have hints +# generated. After it has been dead this long, new hints for it will not be +# created until it has been seen alive and gone down again. +max_hint_window_in_ms: 10800000 # 3 hours +# Maximum throttle in KBs per second, per delivery thread. This will be +# reduced proportionally to the number of nodes in the cluster. (If there +# are two nodes in the cluster, each delivery thread will use the maximum +# rate; if there are three, each will throttle to half of the maximum, +# since we expect two nodes to be delivering hints simultaneously.) +hinted_handoff_throttle_in_kb: 1024 +# Number of threads with which to deliver hints; +# Consider increasing this number when you have multi-dc deployments, since +# cross-dc handoff tends to be slower +max_hints_delivery_threads: 2 + +hints_directory: target/embeddedCassandra/hints + +# The following setting populates the page cache on memtable flush and compaction +# WARNING: Enable this setting only when the whole node's data fits in memory. +# Defaults to: false +# populate_io_cache_on_flush: false + +# Authentication backend, implementing IAuthenticator; used to identify users +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator, +# PasswordAuthenticator}. +# +# - AllowAllAuthenticator performs no checks - set it to disable authentication. +# - PasswordAuthenticator relies on username/password pairs to authenticate +# users. It keeps usernames and hashed passwords in system_auth.credentials table. +# Please increase system_auth keyspace replication factor if you use this authenticator. +authenticator: AllowAllAuthenticator + +# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer, +# CassandraAuthorizer}. +# +# - AllowAllAuthorizer allows any action to any user - set it to disable authorization. +# - CassandraAuthorizer stores permissions in system_auth.permissions table. Please +# increase system_auth keyspace replication factor if you use this authorizer. +authorizer: AllowAllAuthorizer + +# Validity period for permissions cache (fetching permissions can be an +# expensive operation depending on the authorizer, CassandraAuthorizer is +# one example). Defaults to 2000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthorizer. +permissions_validity_in_ms: 2000 + + +# The partitioner is responsible for distributing rows (by key) across +# nodes in the cluster. Any IPartitioner may be used, including your/m +# own as long as it is on the classpath. Out of the box, Cassandra +# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner +# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}. +# +# - RandomPartitioner distributes rows across the cluster evenly by md5. +# This is the default prior to 1.2 and is retained for compatibility. +# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128 +# Hash Function instead of md5. When in doubt, this is the best option. +# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows +# scanning rows in key order, but the ordering can generate hot spots +# for sequential insertion workloads. +# - OrderPreservingPartitioner is an obsolete form of BOP, that stores +# - keys in a less-efficient format and only works with keys that are +# UTF8-encoded Strings. +# - CollatingOPP collates according to EN,US rules rather than lexical byte +# ordering. Use this as an example if you need custom collation. +# +# See http://wiki.apache.org/cassandra/Operations for more on +# partitioners and token selection. +partitioner: org.apache.cassandra.dht.Murmur3Partitioner + +# directories where Cassandra should store data on disk. +data_file_directories: + - target/embeddedCassandra/data + +# commit log +commitlog_directory: target/embeddedCassandra/commitlog + +cdc_raw_directory: target/embeddedCassandra/cdc + +# policy for data disk failures: +# stop: shut down gossip and Thrift, leaving the node effectively dead, but +# can still be inspected via JMX. +# best_effort: stop using the failed disk and respond to requests based on +# remaining available sstables. This means you WILL see obsolete +# data at CL.ONE! +# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra +disk_failure_policy: stop + + +# Maximum size of the key cache in memory. +# +# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the +# minimum, sometimes more. The key cache is fairly tiny for the amount of +# time it saves, so it's worthwhile to use it at large numbers. +# The row cache saves even more time, but must store the whole values of +# its rows, so it is extremely space-intensive. It's best to only use the +# row cache if you have hot rows or static rows. +# +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. +key_cache_size_in_mb: + +# Duration in seconds after which Cassandra should +# safe the keys cache. Caches are saved to saved_caches_directory as +# specified in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 14400 or 4 hours. +key_cache_save_period: 14400 + +# Number of keys from the key cache to save +# Disabled by default, meaning all keys are going to be saved +# key_cache_keys_to_save: 100 + +# Maximum size of the row cache in memory. +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is 0, to disable row caching. +row_cache_size_in_mb: 0 + +# Duration in seconds after which Cassandra should +# safe the row cache. Caches are saved to saved_caches_directory as specified +# in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 0 to disable saving the row cache. +row_cache_save_period: 0 + +# Number of keys from the row cache to save +# Disabled by default, meaning all keys are going to be saved +# row_cache_keys_to_save: 100 + +# saved caches +saved_caches_directory: target/embeddedCassandra/saved_caches + +# commitlog_sync may be either "periodic" or "batch." +# When in batch mode, Cassandra won't ack writes until the commit log +# has been fsynced to disk. It will wait up to +# commitlog_sync_batch_window_in_ms milliseconds for other writes, before +# performing the sync. +# +# commitlog_sync: batch +# commitlog_sync_batch_window_in_ms: 50 +# +# the other option is "periodic" where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 + +# The size of the individual commitlog file segments. A commitlog +# segment may be archived, deleted, or recycled once all the data +# in it (potentially from each columnfamily in the system) has been +# flushed to sstables. +# +# The default size is 32, which is almost always fine, but if you are +# archiving commitlog segments (see commitlog_archiving.properties), +# then you probably want a finer granularity of archiving; 8 or 16 MB +# is reasonable. +commitlog_segment_size_in_mb: 32 + +# any class that implements the SeedProvider interface and has a +# constructor that takes a Map of parameters will do. +seed_provider: + # Addresses of hosts that are deemed contact points. + # Cassandra nodes use this list of hosts to find each other and learn + # the topology of the ring. You must change this if you are running + # multiple nodes! + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # seeds is actually a comma-delimited list of addresses. + # Ex: ",," + - seeds: "127.0.0.1" + + +# For workloads with more data than can fit in memory, Cassandra's +# bottleneck will be reads that need to fetch data from +# disk. "concurrent_reads" should be set to (16 * number_of_drives) in +# order to allow the operations to enqueue low enough in the stack +# that the OS and drives can reorder them. +# +# On the other hand, since writes are almost never IO bound, the ideal +# number of "concurrent_writes" is dependent on the number of cores in +# your system; (8 * number_of_cores) is a good rule of thumb. +concurrent_reads: 32 +concurrent_writes: 32 + +# Total memory to use for memtables. Cassandra will flush the largest +# memtable when this much memory is used. +# If omitted, Cassandra will set it to 1/3 of the heap. +# memtable_total_space_in_mb: 2048 + +# Total space to use for commitlogs. +# If space gets above this value (it will round up to the next nearest +# segment multiple), Cassandra will flush every dirty CF in the oldest +# segment and remove it. +# commitlog_total_space_in_mb: 4096 + +# This sets the amount of memtable flush writer threads. These will +# be blocked by disk io, and each one will hold a memtable in memory +# while blocked. If you have a large heap and many data directories, +# you can increase this value for better flush performance. +# By default this will be set to the amount of data directories defined. +#memtable_flush_writers: 1 + +# the number of full memtables to allow pending flush, that is, +# waiting for a writer thread. At a minimum, this should be set to +# the maximum number of secondary indexes created on a single CF. +#memtable_flush_queue_size: 4 + +# Whether to, when doing sequential writing, fsync() at intervals in +# order to force the operating system to flush the dirty +# buffers. Enable this to avoid sudden dirty buffer flushing from +# impacting read latencies. Almost always a good idea on SSD:s; not +# necessarily on platters. +trickle_fsync: false +trickle_fsync_interval_in_kb: 10240 + +# TCP port, for commands and data +storage_port: 7010 + +# SSL port, for encrypted communication. Unused unless enabled in +# encryption_options +ssl_storage_port: 7011 + +# Address to bind to and tell other Cassandra nodes to connect to. You +# _must_ change this if you want multiple nodes to be able to +# communicate! +# +# Leaving it blank leaves it up to InetAddress.getLocalHost(). This +# will always do the Right Thing *if* the node is properly configured +# (hostname, name resolution, etc), and the Right Thing is to use the +# address associated with the hostname (it might not be). +# +# Setting this to 0.0.0.0 is always wrong. +listen_address: 127.0.0.1 + +start_native_transport: true +# port for the CQL native transport to listen for clients on +native_transport_port: 9042 + +# Whether to start the thrift rpc server. +start_rpc: true + +# Address to broadcast to other Cassandra nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + +# The address to bind the Thrift RPC service to -- clients connect +# here. Unlike ListenAddress above, you *can* specify 0.0.0.0 here if +# you want Thrift to listen on all interfaces. +# +# Leaving this blank has the same effect it does for ListenAddress, +# (i.e. it will be based on the configured hostname of the node). +rpc_address: localhost +# port for Thrift to listen for clients on +rpc_port: 9171 + +# enable or disable keepalive on rpc connections +rpc_keepalive: true + +# Cassandra provides three options for the RPC Server: +# +# sync -> One connection per thread in the rpc pool (see below). +# For a very large number of clients, memory will be your limiting +# factor; on a 64 bit JVM, 128KB is the minimum stack size per thread. +# Connection pooling is very, very strongly recommended. +# +# async -> Nonblocking server implementation with one thread to serve +# rpc connections. This is not recommended for high throughput use +# cases. Async has been tested to be about 50% slower than sync +# or hsha and is deprecated: it will be removed in the next major release. +# +# hsha -> Stands for "half synchronous, half asynchronous." The rpc thread pool +# (see below) is used to manage requests, but the threads are multiplexed +# across the different clients. +# +# The default is sync because on Windows hsha is about 30% slower. On Linux, +# sync/hsha performance is about the same, with hsha of course using less memory. +rpc_server_type: sync + +# Uncomment rpc_min|max|thread to set request pool size. +# You would primarily set max for the sync server to safeguard against +# misbehaved clients; if you do hit the max, Cassandra will block until one +# disconnects before accepting more. The defaults for sync are min of 16 and max +# unlimited. +# +# For the Hsha server, the min and max both default to quadruple the number of +# CPU cores. +# +# This configuration is ignored by the async server. +# +# rpc_min_threads: 16 +# rpc_max_threads: 2048 + +# uncomment to set socket buffer sizes on rpc connections +# rpc_send_buff_size_in_bytes: +# rpc_recv_buff_size_in_bytes: + +# Frame size for thrift (maximum field length). +# 0 disables TFramedTransport in favor of TSocket. This option +# is deprecated; we strongly recommend using Framed mode. +thrift_framed_transport_size_in_mb: 15 + +# The max length of a thrift message, including all fields and +# internal thrift overhead. +thrift_max_message_length_in_mb: 16 + +# Set to true to have Cassandra create a hard link to each sstable +# flushed or streamed locally in a backups/ subdirectory of the +# Keyspace data. Removing these links is the operator's +# responsibility. +incremental_backups: false + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Cassandra won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +snapshot_before_compaction: false + +# Whether or not a snapshot is taken of the data before keyspace truncation +# or dropping of column families. The STRONGLY advised default of true +# should be used to provide data safety. If you set this flag to false, you will +# lose data on truncation or drop. +auto_snapshot: false + +# Add column indexes to a row after its contents reach this size. +# Increase if your column values are large, or if you have a very large +# number of columns. The competing causes are, Cassandra has to +# deserialize this much of the row to read a single column, so you want +# it to be small - at least if you do many partial-row reads - but all +# the index data is read for each access, so you don't want to generate +# that wastefully either. +column_index_size_in_kb: 64 + +# Size limit for rows being compacted in memory. Larger rows will spill +# over to disk and use a slower two-pass compaction process. A message +# will be logged specifying the row key. +#in_memory_compaction_limit_in_mb: 64 + +# Number of simultaneous compactions to allow, NOT including +# validation "compactions" for anti-entropy repair. Simultaneous +# compactions can help preserve read performance in a mixed read/write +# workload, by mitigating the tendency of small sstables to accumulate +# during a single long running compactions. The default is usually +# fine and if you experience problems with compaction running too +# slowly or too fast, you should look at +# compaction_throughput_mb_per_sec first. +# +# This setting has no effect on LeveledCompactionStrategy. +# +# concurrent_compactors defaults to the number of cores. +# Uncomment to make compaction mono-threaded, the pre-0.8 default. +#concurrent_compactors: 1 + +# Multi-threaded compaction. When enabled, each compaction will use +# up to one thread per core, plus one thread per sstable being merged. +# This is usually only useful for SSD-based hardware: otherwise, +# your concern is usually to get compaction to do LESS i/o (see: +# compaction_throughput_mb_per_sec), not more. +#multithreaded_compaction: false + +# Throttles compaction to the given total throughput across the entire +# system. The faster you insert data, the faster you need to compact in +# order to keep the sstable count down, but in general, setting this to +# 16 to 32 times the rate you are inserting data is more than sufficient. +# Setting this to 0 disables throttling. Note that this account for all types +# of compaction, including validation compaction. +compaction_throughput_mb_per_sec: 16 + +# Track cached row keys during compaction, and re-cache their new +# positions in the compacted sstable. Disable if you use really large +# key caches. +#compaction_preheat_key_cache: true + +# Throttles all outbound streaming file transfers on this node to the +# given total throughput in Mbps. This is necessary because Cassandra does +# mostly sequential IO when streaming data during bootstrap or repair, which +# can lead to saturating the network connection and degrading rpc performance. +# When unset, the default is 200 Mbps or 25 MB/s. +# stream_throughput_outbound_megabits_per_sec: 200 + +# How long the coordinator should wait for read operations to complete +read_request_timeout_in_ms: 5000 +# How long the coordinator should wait for seq or index scans to complete +range_request_timeout_in_ms: 10000 +# How long the coordinator should wait for writes to complete +write_request_timeout_in_ms: 2000 +# How long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +cas_contention_timeout_in_ms: 1000 +# How long the coordinator should wait for truncates to complete +# (This can be much longer, because unless auto_snapshot is disabled +# we need to flush first so we can snapshot before removing the data.) +truncate_request_timeout_in_ms: 60000 +# The default timeout for other, miscellaneous operations +request_timeout_in_ms: 10000 + +# Enable operation timeout information exchange between nodes to accurately +# measure request timeouts. If disabled, replicas will assume that requests +# were forwarded to them instantly by the coordinator, which means that +# under overload conditions we will waste that much extra time processing +# already-timed-out requests. +# +# Warning: before enabling this property make sure to ntp is installed +# and the times are synchronized between the nodes. +cross_node_timeout: false + +# Enable socket timeout for streaming operation. +# When a timeout occurs during streaming, streaming is retried from the start +# of the current file. This _can_ involve re-streaming an important amount of +# data, so you should avoid setting the value too low. +# Default value is 0, which never timeout streams. +# streaming_socket_timeout_in_ms: 0 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# endpoint_snitch -- Set this to a class that implements +# IEndpointSnitch. The snitch has two functions: +# - it teaches Cassandra enough about your network topology to route +# requests efficiently +# - it allows Cassandra to spread replicas around your cluster to avoid +# correlated failures. It does this by grouping machines into +# "datacenters" and "racks." Cassandra will do its best not to have +# more than one replica on the same "rack" (which may not actually +# be a physical location) +# +# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER, +# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS +# ARE PLACED. +# +# Out of the box, Cassandra provides +# - SimpleSnitch: +# Treats Strategy order as proximity. This improves cache locality +# when disabling read repair, which can further improve throughput. +# Only appropriate for single-datacenter deployments. +# - PropertyFileSnitch: +# Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-topology.properties. +# - RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's +# IP address, respectively. Unless this happens to match your +# deployment conventions (as it did Facebook's), this is best used +# as an example of writing a custom Snitch class. +# - Ec2Snitch: +# Appropriate for EC2 deployments in a single Region. Loads Region +# and Availability Zone information from the EC2 API. The Region is +# treated as the Datacenter, and the Availability Zone as the rack. +# Only private IPs are used, so this will not work across multiple +# Regions. +# - Ec2MultiRegionSnitch: +# Uses public IPs as broadcast_address to allow cross-region +# connectivity. (Thus, you should set seed addresses to the public +# IP as well.) You will need to open the storage_port or +# ssl_storage_port on the public IP firewall. (For intra-Region +# traffic, Cassandra will switch to the private IP after +# establishing a connection.) +# +# You can use a custom Snitch by setting this to the full class name +# of the snitch, which will be assumed to be on your classpath. +endpoint_snitch: SimpleSnitch + +# controls how often to perform the more expensive part of host score +# calculation +dynamic_snitch_update_interval_in_ms: 100 +# controls how often to reset all host scores, allowing a bad host to +# possibly recover +dynamic_snitch_reset_interval_in_ms: 600000 +# if set greater than zero and read_repair_chance is < 1.0, this will allow +# 'pinning' of replicas to hosts in order to increase cache capacity. +# The badness threshold will control how much worse the pinned host has to be +# before the dynamic snitch will prefer other replicas over it. This is +# expressed as a double which represents a percentage. Thus, a value of +# 0.2 means Cassandra would continue to prefer the static snitch values +# until the pinned host was 20% worse than the fastest. +dynamic_snitch_badness_threshold: 0.1 + +# request_scheduler -- Set this to a class that implements +# RequestScheduler, which will schedule incoming client requests +# according to the specific policy. This is useful for multi-tenancy +# with a single Cassandra cluster. +# NOTE: This is specifically for requests from the client and does +# not affect inter node communication. +# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place +# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of +# client requests to a node with a separate queue for each +# request_scheduler_id. The scheduler is further customized by +# request_scheduler_options as described below. +request_scheduler: org.apache.cassandra.scheduler.NoScheduler + +# Scheduler Options vary based on the type of scheduler +# NoScheduler - Has no options +# RoundRobin +# - throttle_limit -- The throttle_limit is the number of in-flight +# requests per client. Requests beyond +# that limit are queued up until +# running requests can complete. +# The value of 80 here is twice the number of +# concurrent_reads + concurrent_writes. +# - default_weight -- default_weight is optional and allows for +# overriding the default which is 1. +# - weights -- Weights are optional and will default to 1 or the +# overridden default_weight. The weight translates into how +# many requests are handled during each turn of the +# RoundRobin, based on the scheduler id. +# +# request_scheduler_options: +# throttle_limit: 80 +# default_weight: 5 +# weights: +# Keyspace1: 1 +# Keyspace2: 5 + +# request_scheduler_id -- An identifer based on which to perform +# the request scheduling. Currently the only valid option is keyspace. +# request_scheduler_id: keyspace + +# index_interval controls the sampling of entries from the primrary +# row index in terms of space versus time. The larger the interval, +# the smaller and less effective the sampling will be. In technicial +# terms, the interval coresponds to the number of index entries that +# are skipped between taking each sample. All the sampled entries +# must fit in memory. Generally, a value between 128 and 512 here +# coupled with a large key cache size on CFs results in the best trade +# offs. This value is not often changed, however if you have many +# very small rows (many to an OS page), then increasing this will +# often lower memory usage without a impact on performance. +index_interval: 128 + +# Enable or disable inter-node encryption +# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that +# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher +# suite for authentication, key exchange and encryption of the actual data transfers. +# NOTE: No custom encryption options are enabled at the moment +# The available internode options are : all, none, dc, rack +# +# If set to dc cassandra will encrypt the traffic between the DCs +# If set to rack cassandra will encrypt the traffic between the racks +# +# The passwords used in these options must match the passwords used when generating +# the keystore and truststore. For instructions on generating these files, see: +# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore +# +encryption_options: + internode_encryption: none + keystore: conf/.keystore + keystore_password: cassandra + truststore: conf/.truststore + truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] \ No newline at end of file diff --git a/persistence-modules/spring-data-cassandra/pom.xml b/persistence-modules/spring-data-cassandra/pom.xml index 11953a734b..4f323a72d8 100644 --- a/persistence-modules/spring-data-cassandra/pom.xml +++ b/persistence-modules/spring-data-cassandra/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-data-cassandra 0.0.1-SNAPSHOT - jar spring-data-cassandra + jar com.baeldung diff --git a/persistence-modules/spring-data-couchbase-2/README.md b/persistence-modules/spring-data-couchbase-2/README.md index 2e56b25fef..3145fc653a 100644 --- a/persistence-modules/spring-data-couchbase-2/README.md +++ b/persistence-modules/spring-data-couchbase-2/README.md @@ -1,8 +1,8 @@ ## Spring Data Couchbase Tutorial Project ### Relevant Articles: -- [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) +- [Intro to Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) +- [Entity Validation, Optimistic Locking, and Query Consistency 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) ### Overview 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"; diff --git a/persistence-modules/spring-data-eclipselink/pom.xml b/persistence-modules/spring-data-eclipselink/pom.xml index 618fa83ee5..61c28dc26f 100644 --- a/persistence-modules/spring-data-eclipselink/pom.xml +++ b/persistence-modules/spring-data-eclipselink/pom.xml @@ -67,7 +67,6 @@ 1.5.9.RELEASE 2.7.0 - 1.4.196 diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index ee9e71a1cb..9495d56798 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-data-elasticsearch 0.0.1-SNAPSHOT - jar spring-data-elasticsearch + jar com.baeldung diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java index fbf4e5ab99..e43dcdf43e 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java @@ -30,6 +30,13 @@ import org.junit.Test; import com.alibaba.fastjson.JSON; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ public class ElasticSearchManualTest { private List listOfPersons = new ArrayList<>(); private Client client = null; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java similarity index 97% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java index 1f55379418..f9a42050b6 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java @@ -31,9 +31,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.data.es.config.Config; import com.vividsolutions.jts.geom.Coordinate; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * * and further configurations + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class GeoQueriesIntegrationTest { +public class GeoQueriesManualTest { private static final String WONDERS_OF_WORLD = "wonders-of-world"; private static final String WONDERS = "Wonders"; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java similarity index 97% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java index 6ecb11cdbe..bed2e2ff25 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java @@ -27,9 +27,16 @@ import com.baeldung.spring.data.es.model.Article; import com.baeldung.spring.data.es.model.Author; import com.baeldung.spring.data.es.service.ArticleService; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class ElasticSearchIntegrationTest { +public class ElasticSearchManualTest { @Autowired private ElasticsearchTemplate elasticsearchTemplate; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java similarity index 98% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java index 2348c49830..5e24d8398c 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java @@ -41,9 +41,16 @@ import com.baeldung.spring.data.es.model.Article; import com.baeldung.spring.data.es.model.Author; import com.baeldung.spring.data.es.service.ArticleService; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class ElasticSearchQueryIntegrationTest { +public class ElasticSearchQueryManualTest { @Autowired private ElasticsearchTemplate elasticsearchTemplate; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java similarity index 77% rename from persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java index 6f45039c96..c6f095eae9 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java @@ -7,9 +7,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.data.es.config.Config; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class SpringContextIntegrationTest { +public class SpringContextManualTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/persistence-modules/spring-data-gemfire/pom.xml b/persistence-modules/spring-data-gemfire/pom.xml index 292b7387ac..dbb869acf0 100644 --- a/persistence-modules/spring-data-gemfire/pom.xml +++ b/persistence-modules/spring-data-gemfire/pom.xml @@ -2,10 +2,8 @@ 4.0.0 - com.baeldung spring-data-gemfire - 1.0.0-SNAPSHOT - spring-data-gemfire + spring-data-gemfire jar @@ -54,14 +52,6 @@
- - spring-snapshots - Spring Snapshots - http://repo.spring.io/libs-snapshot - - true - - gemstone http://dist.gemstone.com.s3.amazonaws.com/maven/release/ 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..3bd62cbd45 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/README.md @@ -0,0 +1,14 @@ +### Relevant Articles: +- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) +- [JPA Join Types](https://www.baeldung.com/jpa-join-types) +- [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries) +- [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query) +- [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators) +- [Spring Data JPA and Null Parameters](https://www.baeldung.com/spring-data-jpa-null-parameters) +- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections) +- [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable) +- [Spring Data JPA Delete and Relationships](https://www.baeldung.com/spring-data-jpa-delete) +- [Spring Data JPA and Named Entity Graphs](https://www.baeldung.com/spring-data-jpa-named-entity-graphs) +- [Batch Insert/Update with Hibernate/JPA](https://www.baeldung.com/jpa-hibernate-batch-insert-update) +- [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush) +- [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries) 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..08be64670b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/pom.xml @@ -0,0 +1,49 @@ + + + 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 + + + + net.ttddyy + datasource-proxy + ${datasource-proxy.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.springframework + spring-oxm + + + + + 1.4.1 + + \ 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/batchinserts/DatasourceProxyBeanPostProcessor.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/DatasourceProxyBeanPostProcessor.java new file mode 100644 index 0000000000..504357db44 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/DatasourceProxyBeanPostProcessor.java @@ -0,0 +1,53 @@ +package com.baeldung.batchinserts; + +import java.lang.reflect.Method; +import javax.sql.DataSource; +import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; + +@Component +@Profile("batchinserts") +public class DatasourceProxyBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException { + if (bean instanceof DataSource) { + ProxyFactory factory = new ProxyFactory(bean); + factory.setProxyTargetClass(true); + factory.addAdvice(new ProxyDataSourceInterceptor((DataSource) bean)); + return factory.getProxy(); + } + + return bean; + } + + private static class ProxyDataSourceInterceptor implements MethodInterceptor { + + private final DataSource dataSource; + + public ProxyDataSourceInterceptor(final DataSource dataSource) { + this.dataSource = ProxyDataSourceBuilder.create(dataSource).name("Batch-Insert-Logger").asJson().countQuery().logQueryToSysOut().build(); + } + + @Override + public Object invoke(final MethodInvocation invocation) throws Throwable { + Method proxyMethod = ReflectionUtils.findMethod(dataSource.getClass(), invocation.getMethod().getName()); + if (proxyMethod != null) { + return proxyMethod.invoke(dataSource, invocation.getArguments()); + } + return invocation.proceed(); + } + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/School.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/School.java new file mode 100644 index 0000000000..6d2f333ac7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/School.java @@ -0,0 +1,45 @@ +package com.baeldung.batchinserts.model; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class School { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private long id; + + private String name; + + @OneToMany(mappedBy = "school") + private List students; + + 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 List getStudents() { + return students; + } + + public void setStudents(List students) { + this.students = students; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/Student.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/Student.java new file mode 100644 index 0000000000..d38214f122 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/batchinserts/model/Student.java @@ -0,0 +1,44 @@ +package com.baeldung.batchinserts.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private long id; + + private String name; + + @ManyToOne + private School school; + + 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 School getSchool() { + return school; + } + + public void setSchool(School school) { + this.school = school; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java new file mode 100644 index 0000000000..24348d31c5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java @@ -0,0 +1,35 @@ +package com.baeldung.config; + +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.data.repository.init.Jackson2RepositoryPopulatorFactoryBean; +import org.springframework.data.repository.init.UnmarshallerRepositoryPopulatorFactoryBean; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; + +import com.baeldung.entity.Fruit; + +@Configuration +public class JpaPopulators { + + @Bean + public Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulator() throws Exception { + Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean(); + factory.setResources(new Resource[] { new ClassPathResource("fruit-data.json") }); + return factory; + } + + @Bean + public UnmarshallerRepositoryPopulatorFactoryBean repositoryPopulator() { + + Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller(); + unmarshaller.setClassesToBeBound(Fruit.class); + + UnmarshallerRepositoryPopulatorFactoryBean factory = new UnmarshallerRepositoryPopulatorFactoryBean(); + factory.setUnmarshaller(unmarshaller); + factory.setResources(new Resource[] { new ClassPathResource("apple-fruit-data.xml"), new ClassPathResource("guava-fruit-data.xml") }); + return factory; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java new file mode 100644 index 0000000000..deac24548a --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java @@ -0,0 +1,51 @@ +package com.baeldung.datajpadelete.entity; + +import javax.persistence.*; + +@Entity +public class Book { + + @Id + @GeneratedValue + private Long id; + private String title; + + @ManyToOne + private Category category; + + public Book() { + } + + public Book(String title) { + this.title = title; + } + + public Book(String title, Category category) { + this.title = title; + this.category = category; + } + + 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 Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java new file mode 100644 index 0000000000..16f1a4157f --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java @@ -0,0 +1,60 @@ +package com.baeldung.datajpadelete.entity; + +import javax.persistence.*; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Entity +public class Category { + + @Id + @GeneratedValue + private Long id; + private String name; + + @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true) + private List books; + + public Category() { + } + + public Category(String name) { + this.name = name; + } + + public Category(String name, Book... books) { + this.name = name; + this.books = Stream.of(books).collect(Collectors.toList()); + this.books.forEach(x -> x.setCategory(this)); + } + + public Category(String name, List books) { + this.name = name; + this.books = books; + } + + 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 List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java new file mode 100644 index 0000000000..5d0f45f127 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java @@ -0,0 +1,19 @@ +package com.baeldung.datajpadelete.repository; + +import com.baeldung.datajpadelete.entity.Book; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface BookRepository extends CrudRepository { + + long deleteByTitle(String title); + + @Modifying + @Query("delete from Book b where b.title=:title") + void deleteBooks(@Param("title") String title); + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java new file mode 100644 index 0000000000..6fe7058a78 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.datajpadelete.repository; + +import com.baeldung.datajpadelete.entity.Category; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CategoryRepository extends CrudRepository { +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java new file mode 100644 index 0000000000..e6d38f775b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java @@ -0,0 +1,70 @@ +package com.baeldung.derivedquery.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.ZonedDateTime; + +@Table(name = "users") +@Entity +public class User { + + @Id + @GeneratedValue + private Integer id; + private String name; + private Integer age; + private ZonedDateTime birthDate; + private Boolean active; + + public User() { + } + + public User(String name, Integer age, ZonedDateTime birthDate, Boolean active) { + this.name = name; + this.age = age; + this.birthDate = birthDate; + this.active = active; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public ZonedDateTime getBirthDate() { + return birthDate; + } + + public void setBirthDate(ZonedDateTime birthDate) { + this.birthDate = birthDate; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java new file mode 100644 index 0000000000..a23855d96d --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java @@ -0,0 +1,60 @@ +package com.baeldung.derivedquery.repository; + +import com.baeldung.derivedquery.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.List; + +public interface UserRepository extends JpaRepository { + + List findByName(String name); + + List findByNameIs(String name); + + List findByNameEquals(String name); + + List findByNameIsNull(); + + List findByNameNot(String name); + + List findByNameIsNot(String name); + + List findByNameStartingWith(String name); + + List findByNameEndingWith(String name); + + List findByNameContaining(String name); + + List findByNameLike(String name); + + List findByAgeLessThan(Integer age); + + List findByAgeLessThanEqual(Integer age); + + List findByAgeGreaterThan(Integer age); + + List findByAgeGreaterThanEqual(Integer age); + + List findByAgeBetween(Integer startAge, Integer endAge); + + List findByBirthDateAfter(ZonedDateTime birthDate); + + List findByBirthDateBefore(ZonedDateTime birthDate); + + List findByActiveTrue(); + + List findByActiveFalse(); + + List findByAgeIn(Collection ages); + + List findByNameOrBirthDate(String name, ZonedDateTime birthDate); + + List findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active); + + List findByNameOrderByName(String name); + + List findByNameOrderByNameDesc(String name); + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java new file mode 100644 index 0000000000..203cff1e35 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java @@ -0,0 +1,71 @@ +package com.baeldung.embeddable.model; + +import javax.persistence.AttributeOverride; +import javax.persistence.AttributeOverrides; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Company { + + @Id + @GeneratedValue + private Integer id; + + private String name; + + private String address; + + private String phone; + + @Embedded + @AttributeOverrides(value = { + @AttributeOverride( name = "firstName", column = @Column(name = "contact_first_name")), + @AttributeOverride( name = "lastName", column = @Column(name = "contact_last_name")), + @AttributeOverride( name = "phone", column = @Column(name = "contact_phone")) + }) + private ContactPerson contactPerson; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + 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 ContactPerson getContactPerson() { + return contactPerson; + } + + public void setContactPerson(ContactPerson contactPerson) { + this.contactPerson = contactPerson; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java new file mode 100644 index 0000000000..561da80878 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java @@ -0,0 +1,38 @@ +package com.baeldung.embeddable.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class ContactPerson { + + private String firstName; + + private String lastName; + + private String phone; + + 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 getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java new file mode 100644 index 0000000000..f456b15652 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java @@ -0,0 +1,18 @@ +package com.baeldung.embeddable.repositories; + +import com.baeldung.embeddable.model.Company; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +public interface CompanyRepository extends JpaRepository { + + List findByContactPersonFirstName(String firstName); + + @Query("SELECT C FROM Company C WHERE C.contactPerson.firstName = ?1") + List findByContactPersonFirstNameWithJPQL(String firstName); + + @Query(value = "SELECT * FROM company WHERE contact_first_name = ?1", nativeQuery = true) + List findByContactPersonFirstNameWithNativeQuery(String firstName); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java new file mode 100644 index 0000000000..efcae73853 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java @@ -0,0 +1,37 @@ +package com.baeldung.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Customer { + + @Id + @GeneratedValue + private long id; + private String name; + private String email; + + public Customer(String name, String email) { + this.name = name; + this.email = email; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Employee.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Employee.java new file mode 100644 index 0000000000..135439863f --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Employee.java @@ -0,0 +1,36 @@ +package com.baeldung.entity; + +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; + } +} 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..d45ac33db8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java @@ -0,0 +1,40 @@ +package com.baeldung.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@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/entity/Passenger.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Passenger.java new file mode 100644 index 0000000000..3aafbe9afa --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Passenger.java @@ -0,0 +1,78 @@ +package com.baeldung.entity; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class Passenger { + + @Id + @GeneratedValue + @Column(nullable = false) + private Long id; + + @Basic(optional = false) + @Column(nullable = false) + private String firstName; + + @Basic(optional = false) + @Column(nullable = false) + private String lastName; + + private Passenger(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public static Passenger from(String firstName, String lastName) { + return new Passenger(firstName, 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 "Passenger{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Passenger passenger = (Passenger) o; + return Objects.equals(firstName, passenger.firstName) && Objects.equals(lastName, passenger.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(firstName, lastName); + } +} 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/entitygraph/model/Characteristic.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/model/Characteristic.java new file mode 100644 index 0000000000..ae20375572 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/model/Characteristic.java @@ -0,0 +1,43 @@ +package com.baeldung.entitygraph.model; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Characteristic { + + @Id + private Long id; + private String type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn + private Item item; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Item getItem() { + return item; + } + + public void setItem(Item item) { + this.item = item; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/model/Item.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/model/Item.java new file mode 100644 index 0000000000..e90a22ef62 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/model/Item.java @@ -0,0 +1,48 @@ +package com.baeldung.entitygraph.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.OneToMany; + +@Entity +@NamedEntityGraph(name = "Item.characteristics", + attributeNodes = @NamedAttributeNode("characteristics") +) +public class Item { + + @Id + private Long id; + private String name; + + @OneToMany(mappedBy = "item") + private List characteristics = new ArrayList<>(); + + 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 List getCharacteristics() { + return characteristics; + } + + public void setCharacteristics(List characteristics) { + this.characteristics = characteristics; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java new file mode 100644 index 0000000000..9f923ab241 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.entitygraph.repository; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.entitygraph.model.Characteristic; + +public interface CharacteristicsRepository extends JpaRepository { + + @EntityGraph(attributePaths = {"item"}) + Characteristic findByType(String type); + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java new file mode 100644 index 0000000000..b2a5f223b3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.entitygraph.repository; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.entitygraph.model.Item; + +public interface ItemRepository extends JpaRepository { + + @EntityGraph(value = "Item.characteristics", type = EntityGraphType.FETCH) + Item findByName(String name); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/exists/Car.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/exists/Car.java new file mode 100644 index 0000000000..bf09caf6ff --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/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-data-jpa-2/src/main/java/com/baeldung/exists/CarRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/exists/CarRepository.java new file mode 100644 index 0000000000..a54f19f4cd --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/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-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java new file mode 100644 index 0000000000..439f7532f5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java @@ -0,0 +1,45 @@ +package com.baeldung.joins.model; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class Department { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + @OneToMany(mappedBy = "department") + private List employees; + + 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 List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java new file mode 100644 index 0000000000..277274e61c --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java @@ -0,0 +1,69 @@ +package com.baeldung.joins.model; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "joins_employee") +public class Employee { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + private int age; + + @ManyToOne + private Department department; + + @OneToMany(mappedBy = "employee") + private List phones; + + 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 getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Department getDepartment() { + return department; + } + + public void setDepartment(Department department) { + this.department = department; + } + + public List getPhones() { + return phones; + } + + public void setPhones(List phones) { + this.phones = phones; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java new file mode 100644 index 0000000000..41382915b1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java @@ -0,0 +1,44 @@ +package com.baeldung.joins.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Phone { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String number; + + @ManyToOne + private Employee employee; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java new file mode 100644 index 0000000000..bba8bd35c4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/model/Movie.java @@ -0,0 +1,58 @@ +package com.baeldung.like.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Movie { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + private String title; + private String director; + private String rating; + private int duration; + + 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 getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getRating() { + return rating; + } + + public void setRating(String rating) { + this.rating = rating; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.duration = duration; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java new file mode 100644 index 0000000000..241bdd3306 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/like/repository/MovieRepository.java @@ -0,0 +1,41 @@ +package com.baeldung.like.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import com.baeldung.like.model.Movie; + +public interface MovieRepository extends CrudRepository { + + List findByTitleContaining(String title); + + List findByTitleLike(String title); + + List findByTitleContains(String title); + + List findByTitleIsContaining(String title); + + List findByRatingStartsWith(String rating); + + List findByDirectorEndsWith(String director); + + List findByTitleContainingIgnoreCase(String title); + + List findByRatingNotContaining(String rating); + + List findByDirectorNotLike(String director); + + @Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%") + List searchByTitleLike(@Param("title") String title); + + @Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%") + List searchByRatingStartsWith(String rating); + + //Escaping works in SpringBoot >= 2.4.1 + //@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}") + @Query("SELECT m FROM Movie m WHERE m.director LIKE %:#{[0]}") + List searchByDirectorEndsWith(String director); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java new file mode 100644 index 0000000000..0c5a3eac60 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java @@ -0,0 +1,57 @@ +package com.baeldung.projection.model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToOne; + +@Entity +public class Address { + @Id + private Long id; + @OneToOne + private Person person; + private String state; + private String city; + private String street; + private String zipCode; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java new file mode 100644 index 0000000000..d18bd1c72d --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java @@ -0,0 +1,47 @@ +package com.baeldung.projection.model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToOne; + +@Entity +public class Person { + @Id + private Long id; + private String firstName; + private String lastName; + @OneToOne(mappedBy = "person") + private Address address; + + 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; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java new file mode 100644 index 0000000000..c1053f4867 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.projection.repository; + +import com.baeldung.projection.view.AddressView; +import com.baeldung.projection.model.Address; +import org.springframework.data.repository.Repository; + +import java.util.List; + +public interface AddressRepository extends Repository { + List getAddressByState(String state); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java new file mode 100644 index 0000000000..64bc7471e6 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.projection.repository; + +import com.baeldung.projection.model.Person; +import com.baeldung.projection.view.PersonDto; +import com.baeldung.projection.view.PersonView; +import org.springframework.data.repository.Repository; + +public interface PersonRepository extends Repository { + PersonView findByLastName(String lastName); + + PersonDto findByFirstName(String firstName); + + T findByLastName(String lastName, Class type); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java new file mode 100644 index 0000000000..7a24a1e9b9 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java @@ -0,0 +1,7 @@ +package com.baeldung.projection.view; + +public interface AddressView { + String getZipCode(); + + PersonView getPerson(); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java new file mode 100644 index 0000000000..1fd924450b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java @@ -0,0 +1,34 @@ +package com.baeldung.projection.view; + +import java.util.Objects; + +public class PersonDto { + private final String firstName; + private final String lastName; + + public PersonDto(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PersonDto personDto = (PersonDto) o; + return Objects.equals(firstName, personDto.firstName) && Objects.equals(lastName, personDto.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(firstName, lastName); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java new file mode 100644 index 0000000000..36777ec26f --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java @@ -0,0 +1,12 @@ +package com.baeldung.projection.view; + +import org.springframework.beans.factory.annotation.Value; + +public interface PersonView { + String getFirstName(); + + String getLastName(); + + @Value("#{target.firstName + ' ' + target.lastName}") + String getFullName(); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java new file mode 100644 index 0000000000..65b22bbd84 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java @@ -0,0 +1,19 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Customer; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface CustomerRepository extends JpaRepository { + + List findByName(String name); + + List findByNameAndEmail(String name, String email); + + @Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null or c.email = :email)") + List findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email); + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/EmployeeRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/EmployeeRepository.java new file mode 100644 index 0000000000..2c4fee80e0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/EmployeeRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.entity.Employee; + +public interface EmployeeRepository extends JpaRepository { + +} 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..9f92909b66 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java @@ -0,0 +1,27 @@ +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; + +@Repository +public interface FruitRepository extends JpaRepository { + + Long deleteByName(String name); + + List deleteByColor(String color); + + 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/main/java/com/baeldung/repository/PassengerRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/PassengerRepository.java new file mode 100644 index 0000000000..a295a74f1b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/PassengerRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Passenger; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +interface PassengerRepository extends JpaRepository { + + List findByFirstNameIgnoreCase(String firstName); + +} 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/main/resources/apple-fruit-data.xml b/persistence-modules/spring-data-jpa-2/src/main/resources/apple-fruit-data.xml new file mode 100644 index 0000000000..d87ae28f1e --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/apple-fruit-data.xml @@ -0,0 +1,7 @@ + + + + 1 + apple + red + diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/application-batchinserts.properties b/persistence-modules/spring-data-jpa-2/src/main/resources/application-batchinserts.properties new file mode 100644 index 0000000000..4141f5668e --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/application-batchinserts.properties @@ -0,0 +1,6 @@ +spring.jpa.show-sql=false + +spring.jpa.properties.hibernate.jdbc.batch_size=5 +spring.jpa.properties.hibernate.order_inserts=true +spring.jpa.properties.hibernate.order_updates=true +spring.jpa.properties.hibernate.batch_versioned_data=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties b/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties new file mode 100644 index 0000000000..fe2270293b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties @@ -0,0 +1 @@ +spring.datasource.data=classpath:db/import_joins.sql 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/main/resources/db/import_joins.sql b/persistence-modules/spring-data-jpa-2/src/main/resources/db/import_joins.sql new file mode 100644 index 0000000000..e4772d6ff2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/db/import_joins.sql @@ -0,0 +1,13 @@ +INSERT INTO department (id, name) VALUES (1, 'Infra'); +INSERT INTO department (id, name) VALUES (2, 'Accounting'); +INSERT INTO department (id, name) VALUES (3, 'Management'); + +INSERT INTO joins_employee (id, name, age, department_id) VALUES (1, 'Baeldung', '35', 1); +INSERT INTO joins_employee (id, name, age, department_id) VALUES (2, 'John', '35', 2); +INSERT INTO joins_employee (id, name, age, department_id) VALUES (3, 'Jane', '35', 2); + +INSERT INTO phone (id, number, employee_id) VALUES (1, '111', 1); +INSERT INTO phone (id, number, employee_id) VALUES (2, '222', 1); +INSERT INTO phone (id, number, employee_id) VALUES (3, '333', 1); + +COMMIT; diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json b/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json new file mode 100644 index 0000000000..6dc44e2586 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json @@ -0,0 +1,14 @@ +[ + { + "_class": "com.baeldung.entity.Fruit", + "name": "apple", + "color": "red", + "id": 1 + }, + { + "_class": "com.baeldung.entity.Fruit", + "name": "guava", + "color": "green", + "id": 2 + } +] \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml b/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml new file mode 100644 index 0000000000..ffd75bb4bb --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml @@ -0,0 +1,7 @@ + + + + 2 + guava + green + diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaBatchInsertsIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaBatchInsertsIntegrationTest.java new file mode 100644 index 0000000000..9e81dbc04d --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaBatchInsertsIntegrationTest.java @@ -0,0 +1,94 @@ +package com.baeldung.batchinserts; + +import static com.baeldung.batchinserts.TestObjectHelper.createSchool; +import static com.baeldung.batchinserts.TestObjectHelper.createStudent; + +import com.baeldung.batchinserts.model.School; +import com.baeldung.batchinserts.model.Student; +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Transactional +@ActiveProfiles("batchinserts") +public class JpaBatchInsertsIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + private static final int BATCH_SIZE = 5; + + @Transactional + @Test + public void whenInsertingSingleTypeOfEntity_thenCreatesSingleBatch() { + for (int i = 0; i < 10; i++) { + School school = createSchool(i); + entityManager.persist(school); + } + } + + @Transactional + @Test + public void whenFlushingAfterBatch_ThenClearsMemory() { + for (int i = 0; i < 10; i++) { + if (i > 0 && i % BATCH_SIZE == 0) { + entityManager.flush(); + entityManager.clear(); + } + + School school = createSchool(i); + entityManager.persist(school); + } + } + + @Transactional + @Test + public void whenThereAreMultipleEntities_ThenCreatesNewBatch() { + for (int i = 0; i < 10; i++) { + if (i > 0 && i % BATCH_SIZE == 0) { + entityManager.flush(); + entityManager.clear(); + } + + School school = createSchool(i); + entityManager.persist(school); + Student firstStudent = createStudent(school); + Student secondStudent = createStudent(school); + entityManager.persist(firstStudent); + entityManager.persist(secondStudent); + } + } + + @Transactional + @Test + public void whenUpdatingEntities_thenCreatesBatch() { + for (int i = 0; i < 10; i++) { + School school = createSchool(i); + entityManager.persist(school); + } + + entityManager.flush(); + + TypedQuery schoolQuery = entityManager.createQuery("SELECT s from School s", School.class); + List allSchools = schoolQuery.getResultList(); + + for (School school : allSchools) { + school.setName("Updated_" + school.getName()); + } + } + + @After + public void tearDown() { + entityManager.flush(); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaNoBatchInsertsIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaNoBatchInsertsIntegrationTest.java new file mode 100644 index 0000000000..20502c793d --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/JpaNoBatchInsertsIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.batchinserts; + +import static com.baeldung.batchinserts.TestObjectHelper.createSchool; + +import com.baeldung.batchinserts.model.School; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Transactional +@ActiveProfiles("batchinserts") +@TestPropertySource(properties = "spring.jpa.properties.hibernate.jdbc.batch_size=-1") +public class JpaNoBatchInsertsIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Test + public void whenNotConfigured_ThenSendsInsertsSeparately() { + for (int i = 0; i < 10; i++) { + School school = createSchool(i); + entityManager.persist(school); + } + } + + @After + public void tearDown() { + entityManager.flush(); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/TestObjectHelper.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/TestObjectHelper.java new file mode 100644 index 0000000000..fcd26cb721 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/batchinserts/TestObjectHelper.java @@ -0,0 +1,20 @@ +package com.baeldung.batchinserts; + +import com.baeldung.batchinserts.model.School; +import com.baeldung.batchinserts.model.Student; + +public class TestObjectHelper { + + public static School createSchool(int nameIdentifier) { + School school = new School(); + school.setName("School" + (nameIdentifier + 1)); + return school; + } + + public static Student createStudent(School school) { + Student student = new Student(); + student.setName("Student-" + school.getName()); + student.setSchool(school); + return student; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java new file mode 100644 index 0000000000..5f4a36bc0e --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.datajpadelete; + +import com.baeldung.Application; +import com.baeldung.datajpadelete.entity.Book; +import com.baeldung.datajpadelete.repository.BookRepository; +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.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}) +public class DeleteFromRepositoryUnitTest { + + @Autowired + private BookRepository repository; + + Book book1; + Book book2; + + @Before + public void setup() { + book1 = new Book("The Hobbit"); + book2 = new Book("All Quiet on the Western Front"); + + repository.saveAll(Arrays.asList(book1, book2)); + } + + @After + public void teardown() { + repository.deleteAll(); + } + + @Test + public void whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful() { + repository.deleteById(book1.getId()); + + assertThat(repository.count()).isEqualTo(1); + } + + @Test + public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty() { + repository.deleteAll(); + + assertThat(repository.count()).isEqualTo(0); + } + + @Test + @Transactional + public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() { + long deletedRecords = repository.deleteByTitle("The Hobbit"); + + assertThat(deletedRecords).isEqualTo(1); + } + + @Test + @Transactional + public void whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful() { + repository.deleteBooks("The Hobbit"); + + assertThat(repository.count()).isEqualTo(1); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java new file mode 100644 index 0000000000..6275ace6e0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.datajpadelete; + +import com.baeldung.Application; +import com.baeldung.datajpadelete.entity.Book; +import com.baeldung.datajpadelete.entity.Category; +import com.baeldung.datajpadelete.repository.BookRepository; +import com.baeldung.datajpadelete.repository.CategoryRepository; +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.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}) +public class DeleteInRelationshipsUnitTest { + + @Autowired + private BookRepository bookRepository; + + @Autowired + private CategoryRepository categoryRepository; + + @Before + public void setup() { + Book book1 = new Book("The Hobbit"); + Category category1 = new Category("Cat1", book1); + categoryRepository.save(category1); + + Book book2 = new Book("All Quiet on the Western Front"); + Category category2 = new Category("Cat2", book2); + categoryRepository.save(category2); + } + + @After + public void teardown() { + bookRepository.deleteAll(); + categoryRepository.deleteAll(); + } + + @Test + public void whenDeletingCategories_thenBooksShouldAlsoBeDeleted() { + categoryRepository.deleteAll(); + + assertThat(bookRepository.count()).isEqualTo(0); + assertThat(categoryRepository.count()).isEqualTo(0); + } + + @Test + public void whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted() { + bookRepository.deleteAll(); + + assertThat(bookRepository.count()).isEqualTo(0); + assertThat(categoryRepository.count()).isEqualTo(2); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java new file mode 100644 index 0000000000..188ed5d4d0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java @@ -0,0 +1,172 @@ +package com.baeldung.derivedquery.repository; + +import com.baeldung.Application; +import com.baeldung.derivedquery.entity.User; +import com.baeldung.derivedquery.repository.UserRepository; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; +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.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class UserRepositoryTest { + + private static final String USER_NAME_ADAM = "Adam"; + private static final String USER_NAME_EVE = "Eve"; + private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now(); + + @Autowired + private UserRepository userRepository; + + @Before + public void setUp() { + + User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true); + User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false); + User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true); + User user4 = new User(null, 30, BIRTHDATE, false); + + userRepository.saveAll(Arrays.asList(user1, user2, user3, user4)); + } + + @After + public void tearDown() { + + userRepository.deleteAll(); + } + + @Test + public void whenFindByName_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByName(USER_NAME_ADAM).size()); + } + + @Test + public void whenFindByNameIsNull_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameIsNull().size()); + } + + @Test + public void whenFindByNameNot_thenReturnsCorrectResult() { + + assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM).get(0).getName()); + } + + @Test + public void whenFindByNameStartingWith_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameStartingWith("A").size()); + } + + @Test + public void whenFindByNameEndingWith_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameEndingWith("e").size()); + } + + @Test + public void whenByNameContaining_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameContaining("v").size()); + } + + + @Test + public void whenByNameLike_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameEndingWith("%d%m").size()); + } + + @Test + public void whenByAgeLessThan_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeLessThan(25).size()); + } + + + @Test + public void whenByAgeLessThanEqual_thenReturnsCorrectResult() { + + assertEquals(3, userRepository.findByAgeLessThanEqual(25).size()); + } + + @Test + public void whenByAgeGreaterThan_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByAgeGreaterThan(25).size()); + } + + @Test + public void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeGreaterThanEqual(25).size()); + } + + @Test + public void whenByAgeBetween_thenReturnsCorrectResult() { + + assertEquals(4, userRepository.findByAgeBetween(20, 30).size()); + } + + @Test + public void whenByBirthDateAfter_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(4, userRepository.findByBirthDateAfter(yesterday).size()); + } + + @Test + public void whenByBirthDateBefore_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(0, userRepository.findByBirthDateBefore(yesterday).size()); + } + + @Test + public void whenByActiveTrue_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveTrue().size()); + } + + @Test + public void whenByActiveFalse_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveFalse().size()); + } + + + @Test + public void whenByAgeIn_thenReturnsCorrectResult() { + + final List ages = Arrays.asList(20, 25); + assertEquals(3, userRepository.findByAgeIn(ages).size()); + } + + @Test + public void whenByNameOrBirthDate() { + + assertEquals(4, userRepository.findByNameOrBirthDate(USER_NAME_ADAM, BIRTHDATE).size()); + } + + @Test + public void whenByNameOrBirthDateAndActive() { + + assertEquals(3, userRepository.findByNameOrBirthDateAndActive(USER_NAME_ADAM, BIRTHDATE, false).size()); + } + + @Test + public void whenByNameOrderByName() { + + assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM).size()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java new file mode 100644 index 0000000000..b4c365a2d9 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java @@ -0,0 +1,125 @@ +package com.baeldung.embeddable; + +import com.baeldung.Application; +import com.baeldung.embeddable.model.Company; +import com.baeldung.embeddable.model.ContactPerson; +import com.baeldung.embeddable.repositories.CompanyRepository; +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.transaction.annotation.Transactional; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}) +public class EmbeddableIntegrationTest { + + @Autowired + private CompanyRepository companyRepository; + + @Test + @Transactional + public void whenInsertingCompany_thenEmbeddedContactPersonDetailsAreMapped() { + ContactPerson contactPerson = new ContactPerson(); + contactPerson.setFirstName("First"); + contactPerson.setLastName("Last"); + contactPerson.setPhone("123-456-789"); + + Company company = new Company(); + company.setName("Company"); + company.setAddress("1st street"); + company.setPhone("987-654-321"); + company.setContactPerson(contactPerson); + + companyRepository.save(company); + + Company result = companyRepository.getOne(company.getId()); + + assertEquals("Company", result.getName()); + assertEquals("1st street", result.getAddress()); + assertEquals("987-654-321", result.getPhone()); + assertEquals("First", result.getContactPerson().getFirstName()); + assertEquals("Last", result.getContactPerson().getLastName()); + assertEquals("123-456-789", result.getContactPerson().getPhone()); + } + + @Test + @Transactional + public void whenFindingCompanyByContactPersonAttribute_thenCompanyIsReturnedProperly() { + ContactPerson contactPerson = new ContactPerson(); + contactPerson.setFirstName("Name"); + contactPerson.setLastName("Last"); + contactPerson.setPhone("123-456-789"); + + Company company = new Company(); + company.setName("Company"); + company.setAddress("1st street"); + company.setPhone("987-654-321"); + company.setContactPerson(contactPerson); + + companyRepository.save(company); + + List result = companyRepository.findByContactPersonFirstName("Name"); + + assertEquals(1, result.size()); + + result = companyRepository.findByContactPersonFirstName("FirstName"); + + assertEquals(0, result.size()); + } + + @Test + @Transactional + public void whenFindingCompanyByContactPersonAttributeWithJPQL_thenCompanyIsReturnedProperly() { + ContactPerson contactPerson = new ContactPerson(); + contactPerson.setFirstName("@QueryName"); + contactPerson.setLastName("Last"); + contactPerson.setPhone("123-456-789"); + + Company company = new Company(); + company.setName("Company"); + company.setAddress("1st street"); + company.setPhone("987-654-321"); + company.setContactPerson(contactPerson); + + companyRepository.save(company); + + List result = companyRepository.findByContactPersonFirstNameWithJPQL("@QueryName"); + + assertEquals(1, result.size()); + + result = companyRepository.findByContactPersonFirstNameWithJPQL("FirstName"); + + assertEquals(0, result.size()); + } + + @Test + @Transactional + public void whenFindingCompanyByContactPersonAttributeWithNativeQuery_thenCompanyIsReturnedProperly() { + ContactPerson contactPerson = new ContactPerson(); + contactPerson.setFirstName("NativeQueryName"); + contactPerson.setLastName("Last"); + contactPerson.setPhone("123-456-789"); + + Company company = new Company(); + company.setName("Company"); + company.setAddress("1st street"); + company.setPhone("987-654-321"); + company.setContactPerson(contactPerson); + + companyRepository.save(company); + + List result = companyRepository.findByContactPersonFirstNameWithNativeQuery("NativeQueryName"); + + assertEquals(1, result.size()); + + result = companyRepository.findByContactPersonFirstNameWithNativeQuery("FirstName"); + + assertEquals(0, result.size()); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java new file mode 100644 index 0000000000..24880a5dff --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.entitygraph; + +import static org.assertj.core.api.Assertions.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.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.entitygraph.model.Characteristic; +import com.baeldung.entitygraph.model.Item; +import com.baeldung.entitygraph.repository.CharacteristicsRepository; +import com.baeldung.entitygraph.repository.ItemRepository; + +@DataJpaTest +@RunWith(SpringRunner.class) +@Sql(scripts = "/entitygraph-data.sql") +public class EntityGraphIntegrationTest { + + @Autowired + private ItemRepository itemRepo; + + @Autowired + private CharacteristicsRepository characteristicsRepo; + + @Test + public void givenEntityGraph_whenCalled_shouldRetrunDefinedFields() { + Item item = itemRepo.findByName("Table"); + assertThat(item.getId()).isEqualTo(1L); + } + + @Test + public void givenAdhocEntityGraph_whenCalled_shouldRetrunDefinedFields() { + Characteristic characteristic = characteristicsRepo.findByType("Rigid"); + assertThat(characteristic.getId()).isEqualTo(1L); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java new file mode 100644 index 0000000000..d99f6671a3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java @@ -0,0 +1,87 @@ +package com.baeldung.exists; + +import com.baeldung.Application; +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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.ignoreCase; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}) +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/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java new file mode 100644 index 0000000000..9b0d23f3e4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.joins; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.baeldung.joins.model.Department; +import com.baeldung.joins.model.Phone; +import java.util.Collection; +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@DataJpaTest +@ActiveProfiles("joins") +public class JpaJoinsIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Test + public void whenPathExpressionIsUsedForSingleValuedAssociation_thenCreatesImplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT e.department FROM Employee e", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e JOIN e.department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenInnerJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e INNER JOIN e.department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenEntitiesAreListedInFromAndMatchedInWhere_ThenCreatesJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d WHERE e.department = d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenEntitiesAreListedInFrom_ThenCreatesCartesianProduct() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(9); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Management", "Infra", "Accounting", "Management", "Infra", "Accounting", "Management"); + } + + @Test + public void whenCollectionValuedAssociationIsJoined_ThenCanSelect() { + TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph WHERE ph LIKE '1%'", Phone.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(1); + } + + @Test + public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() { + TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.department d JOIN e.phones ph WHERE d.name IS NOT NULL", Phone.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("number") + .containsOnly("111", "222", "333"); + } + + @Test + public void whenLeftKeywordIsSpecified_thenCreatesOuterJoinAndIncludesNonMatched() { + TypedQuery query = entityManager.createQuery("SELECT DISTINCT d FROM Department d LEFT JOIN d.employees e", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Management"); + } + + @Test + public void whenFetchKeywordIsSpecified_ThenCreatesFetchJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenLeftAndFetchKeywordsAreSpecified_ThenCreatesOuterFetchJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Department d LEFT JOIN FETCH d.employees", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(4); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting", "Management"); + } + + @Test + public void whenCollectionValuedAssociationIsSpecifiedInSelect_ThenReturnsCollections() { + TypedQuery query = entityManager.createQuery("SELECT e.phones FROM Employee e", Collection.class); + + List resultList = query.getResultList(); + + assertThat(resultList).extracting("number").containsOnly("111", "222", "333"); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java new file mode 100644 index 0000000000..99d7080792 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java @@ -0,0 +1,88 @@ +package com.baeldung.like; + +import static org.junit.Assert.assertEquals; +import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; + +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.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.like.model.Movie; +import com.baeldung.like.repository.MovieRepository; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Sql(scripts = { "/test-movie-data.sql" }) +@Sql(scripts = "/test-movie-cleanup.sql", executionPhase = AFTER_TEST_METHOD) +public class MovieRepositoryIntegrationTest { + @Autowired + private MovieRepository movieRepository; + + @Test + public void givenPartialTitle_WhenFindByTitleContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleLike("%in%"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleIsContaining("in"); + assertEquals(3, results.size()); + + results = movieRepository.findByTitleContains("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_WhenFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenFindByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialTitle_WhenFindByTitleContainingIgnoreCase_ThenMoviesShouldReturn() { + List results = movieRepository.findByTitleContainingIgnoreCase("the"); + assertEquals(2, results.size()); + } + + @Test + public void givenPartialTitle_WhenSearchByTitleLike_ThenMoviesShouldReturn() { + List results = movieRepository.searchByTitleLike("in"); + assertEquals(3, results.size()); + } + + @Test + public void givenStartOfRating_SearchFindByRatingStartsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByRatingStartsWith("PG"); + assertEquals(6, results.size()); + } + + @Test + public void givenLastName_WhenSearchByDirectorEndsWith_ThenMoviesShouldReturn() { + List results = movieRepository.searchByDirectorEndsWith("Burton"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialRating_findByRatingNotContaining_ThenMoviesShouldReturn() { + List results = movieRepository.findByRatingNotContaining("PG"); + assertEquals(1, results.size()); + } + + @Test + public void givenPartialDirector_WhenFindByDirectorNotLike_ThenMoviesShouldReturn() { + List results = movieRepository.findByDirectorNotLike("An%"); + assertEquals(5, results.size()); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java new file mode 100644 index 0000000000..96eaf4ed07 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java @@ -0,0 +1,63 @@ +package com.baeldung.projection; + +import com.baeldung.projection.model.Person; +import com.baeldung.projection.repository.AddressRepository; +import com.baeldung.projection.repository.PersonRepository; +import com.baeldung.projection.view.AddressView; +import com.baeldung.projection.view.PersonDto; +import com.baeldung.projection.view.PersonView; +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.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; + +@DataJpaTest +@RunWith(SpringRunner.class) +@Sql(scripts = "/projection-insert-data.sql") +@Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD) +public class JpaProjectionIntegrationTest { + @Autowired + private AddressRepository addressRepository; + + @Autowired + private PersonRepository personRepository; + + @Test + public void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned() { + AddressView addressView = addressRepository.getAddressByState("CA").get(0); + assertThat(addressView.getZipCode()).isEqualTo("90001"); + + PersonView personView = addressView.getPerson(); + assertThat(personView.getFirstName()).isEqualTo("John"); + assertThat(personView.getLastName()).isEqualTo("Doe"); + } + + @Test + public void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned() { + PersonView personView = personRepository.findByLastName("Doe"); + assertThat(personView.getFullName()).isEqualTo("John Doe"); + } + + @Test + public void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned() { + PersonDto personDto = personRepository.findByFirstName("John"); + assertThat(personDto.getFirstName()).isEqualTo("John"); + assertThat(personDto.getLastName()).isEqualTo("Doe"); + } + + @Test + public void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned() { + Person person = personRepository.findByLastName("Doe", Person.class); + PersonView personView = personRepository.findByLastName("Doe", PersonView.class); + PersonDto personDto = personRepository.findByLastName("Doe", PersonDto.class); + + assertThat(person.getFirstName()).isEqualTo("John"); + assertThat(personView.getFirstName()).isEqualTo("John"); + assertThat(personDto.getFirstName()).isEqualTo("John"); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java new file mode 100644 index 0000000000..5d6457ce30 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Customer; +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.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@DataJpaTest +@RunWith(SpringRunner.class) +public class CustomerRepositoryIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private CustomerRepository repository; + + @Before + public void before() { + entityManager.persist(new Customer("A", "A@example.com")); + entityManager.persist(new Customer("D", null)); + entityManager.persist(new Customer("D", "D@example.com")); + } + + @Test + public void givenQueryMethod_whenEmailIsNull_thenFoundByNullEmail() { + List customers = repository.findByNameAndEmail("D", null); + + assertEquals(1, customers.size()); + Customer actual = customers.get(0); + + assertEquals(null, actual.getEmail()); + assertEquals("D", actual.getName()); + } + + @Test + public void givenQueryMethod_whenEmailIsAbsent_thenIgnoreEmail() { + List customers = repository.findByName("D"); + + assertEquals(2, customers.size()); + } + + @Test + public void givenQueryAnnotation_whenEmailIsNull_thenIgnoreEmail() { + List customers = repository.findCustomerByNameAndEmail("D", null); + + assertEquals(2, customers.size()); + } + + @After + public void cleanUp() { + repository.deleteAll(); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java new file mode 100644 index 0000000000..ebeed276c9 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.repository; + +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.entity.Employee; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class EmployeeRepositoryIntegrationTest { + + private static final Employee EMPLOYEE1 = new Employee(1L, "John"); + private static final Employee EMPLOYEE2 = new Employee(2L, "Alice"); + + @Autowired + private EmployeeRepository employeeRepository; + + @Test + public void givenEmployeeEntity_whenInsertWithSave_ThenEmployeeIsPersisted() { + employeeRepository.save(EMPLOYEE1); + assertEmployeePersisted(EMPLOYEE1); + } + + @Test + public void givenEmployeeEntity_whenInsertWithSaveAndFlush_ThenEmployeeIsPersisted() { + employeeRepository.saveAndFlush(EMPLOYEE2); + assertEmployeePersisted(EMPLOYEE2); + } + + private void assertEmployeePersisted(Employee input) { + Employee employee = employeeRepository.getOne(input.getId()); + assertThat(employee).isNotNull(); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java new file mode 100644 index 0000000000..29ef52dcef --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java @@ -0,0 +1,38 @@ +package com.baeldung.repository; + +import static org.junit.Assert.assertEquals; + +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.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.entity.Fruit; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class FruitPopulatorTest { + + @Autowired + private FruitRepository fruitRepository; + + @Test + public void givenFruitJsonPopulatorThenShouldInsertRecordOnStart() { + + List fruits = fruitRepository.findAll(); + assertEquals("record count is not matching", 2, fruits.size()); + + fruits.forEach(fruit -> { + if (1 == fruit.getId()) { + assertEquals("apple", fruit.getName()); + assertEquals("red", fruit.getColor()); + } else if (2 == fruit.getId()) { + assertEquals("guava", fruit.getName()); + assertEquals("green", fruit.getColor()); + } + }); + } +} 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..866cf1157b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.repository; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +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_ThenDeletedFruitsShouldReturn() { + + 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_ThenDeletedFruitCountShouldReturn() { + + 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_ThenDeletedFruitsShouldReturn() { + + 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_ThenDeletedFruitCountShouldReturn() { + + Long deletedFruitCount = fruitRepository.removeByName("apple"); + + assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue()); + } + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenDeletedByColorOrName_ThenDeletedFruitsShouldReturn() { + + 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 diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java new file mode 100644 index 0000000000..f96f0249d7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Passenger; +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 javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.core.IsNot.not; + +@DataJpaTest +@RunWith(SpringRunner.class) +public class PassengerRepositoryIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private PassengerRepository repository; + + @Before + public void before() { + entityManager.persist(Passenger.from("Jill", "Smith")); + entityManager.persist(Passenger.from("Eve", "Jackson")); + entityManager.persist(Passenger.from("Fred", "Bloggs")); + entityManager.persist(Passenger.from("Ricki", "Bobbie")); + entityManager.persist(Passenger.from("Siya", "Kolisi")); + } + + @Test + public void givenPassengers_whenMatchingIgnoreCase_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith"); + Passenger eve = Passenger.from("Eve", "Jackson"); + Passenger fred = Passenger.from("Fred", "Bloggs"); + Passenger siya = Passenger.from("Siya", "Kolisi"); + Passenger ricki = Passenger.from("Ricki", "Bobbie"); + + 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))); + + } +} 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/entitygraph-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/entitygraph-data.sql new file mode 100644 index 0000000000..685ec2c605 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/entitygraph-data.sql @@ -0,0 +1,7 @@ +INSERT INTO Item(id,name) VALUES (1,'Table'); +INSERT INTO Item(id,name) VALUES (2,'Bottle'); + +INSERT INTO Characteristic(id,item_id, type) VALUES (1,1,'Rigid'); +INSERT INTO Characteristic(id,item_id,type) VALUES (2,1,'Big'); +INSERT INTO Characteristic(id,item_id,type) VALUES (3,2,'Fragile'); +INSERT INTO Characteristic(id,item_id,type) VALUES (4,2,'Small'); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql new file mode 100644 index 0000000000..d34f6f0636 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql @@ -0,0 +1,2 @@ +DELETE FROM address; +DELETE FROM person; \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql new file mode 100644 index 0000000000..544dcc4b88 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql @@ -0,0 +1,2 @@ +INSERT INTO person(id,first_name,last_name) VALUES (1,'John','Doe'); +INSERT INTO address(id,person_id,state,city,street,zip_code) VALUES (1,1,'CA', 'Los Angeles', 'Standford Ave', '90001'); \ 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 diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql new file mode 100644 index 0000000000..90aa15307c --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-cleanup.sql @@ -0,0 +1 @@ +DELETE FROM Movie; \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql new file mode 100644 index 0000000000..37f8e4fe64 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-movie-data.sql @@ -0,0 +1,7 @@ +INSERT INTO movie(id, title, director, rating, duration) VALUES(1, 'Godzilla: King of the Monsters', ' Michael Dougherty', 'PG-13', 132); +INSERT INTO movie(id, title, director, rating, duration) VALUES(2, 'Avengers: Endgame', 'Anthony Russo', 'PG-13', 181); +INSERT INTO movie(id, title, director, rating, duration) VALUES(3, 'Captain Marvel', 'Anna Boden', 'PG-13', 123); +INSERT INTO movie(id, title, director, rating, duration) VALUES(4, 'Dumbo', 'Tim Burton', 'PG', 112); +INSERT INTO movie(id, title, director, rating, duration) VALUES(5, 'Booksmart', 'Olivia Wilde', 'R', 102); +INSERT INTO movie(id, title, director, rating, duration) VALUES(6, 'Aladdin', 'Guy Ritchie', 'PG', 128); +INSERT INTO movie(id, title, director, rating, duration) VALUES(7, 'The Sun Is Also a Star', 'Ry Russo-Young', 'PG-13', 100); 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 diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index e240ae6d33..e85d8a8487 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -5,8 +5,7 @@ ### 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) +- [An Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) - [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) @@ -17,6 +16,12 @@ - [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) +- [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: diff --git a/persistence-modules/spring-data-jpa/pom.xml b/persistence-modules/spring-data-jpa/pom.xml index 786e587734..af92f331d1 100644 --- a/persistence-modules/spring-data-jpa/pom.xml +++ b/persistence-modules/spring-data-jpa/pom.xml @@ -27,21 +27,46 @@ org.hibernate hibernate-envers
+ com.h2database h2 + + + org.testcontainers + postgresql + ${testcontainers.postgresql.version} + test + + + + org.postgresql + postgresql + ${postgresql.version} + + + org.springframework.security spring-security-test test + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + com.google.guava guava - 21.0 + ${guava.version} @@ -64,5 +89,12 @@ test
+ + + com.baeldung.boot.Application + 1.10.6 + 42.2.5 + 21.0 + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/Application.java similarity index 75% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/Application.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/Application.java index 72d29d9fa5..1f078801e2 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/Application.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/Application.java @@ -1,10 +1,11 @@ -package com.baeldung; +package com.baeldung.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl; +import com.baeldung.boot.daos.impl.ExtendedRepositoryImpl; +import com.baeldung.multipledb.MultipleDbApplication; @SpringBootApplication @EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/config/PersistenceConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/config/PersistenceConfiguration.java new file mode 100644 index 0000000000..35a603d9f4 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/config/PersistenceConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.config; + +import com.baeldung.boot.services.IBarService; +import com.baeldung.boot.services.impl.BarSpringDataJpaService; +import org.springframework.context.annotation.*; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@Profile("!tc") +@EnableTransactionManagement +@EnableJpaAuditing +public class PersistenceConfiguration { + + @Bean + public IBarService barSpringDataJpaService() { + return new BarSpringDataJpaService(); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ArticleRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ArticleRepository.java similarity index 90% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ArticleRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ArticleRepository.java index 8402c099d9..73397ad42e 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ArticleRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ArticleRepository.java @@ -1,10 +1,11 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; -import com.baeldung.domain.Article; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.baeldung.boot.domain.Article; + import java.util.Date; import java.util.List; 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/boot/daos/CustomItemRepository.java similarity index 74% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomItemRepository.java index ba077ccf1f..0aebe34921 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/boot/daos/CustomItemRepository.java @@ -1,8 +1,8 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import org.springframework.stereotype.Repository; -import com.baeldung.domain.Item; +import com.baeldung.boot.domain.Item; @Repository public interface CustomItemRepository { @@ -12,4 +12,5 @@ public interface CustomItemRepository { Item findItemById(Long id); void findThenDelete(Long id); + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemTypeRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java similarity index 71% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemTypeRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java index 81ebdf3fda..832d61408c 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemTypeRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java @@ -1,8 +1,8 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import org.springframework.stereotype.Repository; -import com.baeldung.domain.ItemType; +import com.baeldung.boot.domain.ItemType; @Repository public interface CustomItemTypeRepository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomerRepository.java new file mode 100644 index 0000000000..2f1af6ac55 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/CustomerRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.boot.daos; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.boot.domain.Customer; + +/** + * JPA CrudRepository interface + * + * @author ysharma2512 + * + */ +public interface CustomerRepository extends CrudRepository{ + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java similarity index 90% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java index 9e82f02fa6..adb2af4320 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import java.io.Serializable; import java.util.List; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedStudentRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java similarity index 54% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedStudentRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java index 199e4e5ff6..c9b0192536 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ExtendedStudentRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java @@ -1,6 +1,6 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; -import com.baeldung.domain.Student; +import com.baeldung.boot.domain.Student; public interface ExtendedStudentRepository extends ExtendedRepository { } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/IBarCrudRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IBarCrudRepository.java similarity index 71% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/IBarCrudRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IBarCrudRepository.java index 54a7d77691..921fabe3fb 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/IBarCrudRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IBarCrudRepository.java @@ -1,8 +1,9 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; -import com.baeldung.domain.Bar; import org.springframework.data.repository.CrudRepository; +import com.baeldung.boot.domain.Bar; + import java.io.Serializable; public interface IBarCrudRepository extends CrudRepository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/IFooDao.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IFooDao.java similarity index 83% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/IFooDao.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IFooDao.java index bb3c229945..d537772076 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/IFooDao.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/IFooDao.java @@ -1,10 +1,11 @@ -package com.baeldung.dao; +package com.baeldung.boot.daos; -import com.baeldung.domain.Foo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.baeldung.boot.domain.Foo; + public interface IFooDao extends JpaRepository { @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/InventoryRepository.java similarity index 63% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/InventoryRepository.java index a575f0b915..606f3993d5 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/InventoryRepository.java @@ -1,7 +1,8 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; -import com.baeldung.domain.MerchandiseEntity; import org.springframework.data.repository.CrudRepository; +import com.baeldung.boot.domain.MerchandiseEntity; + public interface InventoryRepository extends CrudRepository { } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ItemTypeRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java similarity index 76% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ItemTypeRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java index 2af83bc322..413c09e968 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ItemTypeRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java @@ -1,9 +1,9 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import com.baeldung.domain.ItemType; +import com.baeldung.boot.domain.ItemType; @Repository public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository, CustomItemRepository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/LocationRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/LocationRepository.java similarity index 72% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/LocationRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/LocationRepository.java index 27bbe27af0..697ce295d0 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/LocationRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/LocationRepository.java @@ -1,9 +1,9 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import com.baeldung.domain.Location; +import com.baeldung.boot.domain.Location; @Repository public interface LocationRepository extends JpaRepository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ReadOnlyLocationRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java similarity index 79% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ReadOnlyLocationRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java index 8f68cdbbe5..3a2ea3cda5 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/ReadOnlyLocationRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java @@ -1,10 +1,10 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import java.util.Optional; import org.springframework.data.repository.Repository; -import com.baeldung.domain.Location; +import com.baeldung.boot.domain.Location; @org.springframework.stereotype.Repository public interface ReadOnlyLocationRepository extends Repository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/StoreRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/StoreRepository.java similarity index 79% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/StoreRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/StoreRepository.java index 9318c32ee9..ae13f75f66 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/StoreRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/StoreRepository.java @@ -1,11 +1,11 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import com.baeldung.domain.Store; +import com.baeldung.boot.domain.Store; @Repository public interface StoreRepository extends JpaRepository { 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/boot/daos/impl/CustomItemRepositoryImpl.java similarity index 83% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/CustomItemRepositoryImpl.java index 53def88af0..820a2cdd41 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/boot/daos/impl/CustomItemRepositoryImpl.java @@ -1,12 +1,12 @@ -package com.baeldung.dao.repositories.impl; +package com.baeldung.boot.daos.impl; import javax.persistence.EntityManager; 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.boot.daos.CustomItemRepository; +import com.baeldung.boot.domain.Item; @Repository public class CustomItemRepositoryImpl implements CustomItemRepository { @@ -29,4 +29,5 @@ public class CustomItemRepositoryImpl implements CustomItemRepository { final Item item = entityManager.find(Item.class, id); entityManager.remove(item); } + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemTypeRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java similarity index 84% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemTypeRepositoryImpl.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java index 2b49f2380c..d7cba7c2c6 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemTypeRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java @@ -1,4 +1,4 @@ -package com.baeldung.dao.repositories.impl; +package com.baeldung.boot.daos.impl; import javax.persistence.EntityManager; @@ -7,8 +7,8 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; -import com.baeldung.domain.ItemType; -import com.baeldung.dao.repositories.CustomItemTypeRepository; +import com.baeldung.boot.daos.CustomItemTypeRepository; +import com.baeldung.boot.domain.ItemType; @Repository public class CustomItemTypeRepositoryImpl implements CustomItemTypeRepository { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/ExtendedRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java similarity index 93% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/ExtendedRepositoryImpl.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java index f6f06efb51..fbe6695844 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/ExtendedRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java @@ -1,4 +1,4 @@ -package com.baeldung.dao.repositories.impl; +package com.baeldung.boot.daos.impl; import java.io.Serializable; import java.util.List; @@ -10,10 +10,11 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import javax.transaction.Transactional; -import com.baeldung.dao.repositories.ExtendedRepository; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; +import com.baeldung.boot.daos.ExtendedRepository; + public class ExtendedRepositoryImpl extends SimpleJpaRepository implements ExtendedRepository { private EntityManager entityManager; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/PersonInsertRepository.java similarity index 51% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/PersonInsertRepository.java index 341db1615d..373532e1c3 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/impl/PersonInsertRepository.java @@ -1,24 +1,31 @@ -package com.baeldung.dao.repositories.impl; +package com.baeldung.boot.daos.impl; -import com.baeldung.dao.repositories.PersonQueryInsertRepository; -import com.baeldung.domain.Person; +import org.springframework.stereotype.Repository; + +import com.baeldung.boot.domain.Person; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.Transactional; -@Transactional -public class PersonQueryInsertRepositoryImpl implements PersonQueryInsertRepository { +@Repository +public class PersonInsertRepository { @PersistenceContext private EntityManager entityManager; - @Override - public void insert(Person person) { - entityManager.createNativeQuery("INSERT INTO person (id,first_name, last_name) VALUES (?,?,?)") + @Transactional + public void insertWithQuery(Person person) { + entityManager.createNativeQuery("INSERT INTO person (id, first_name, last_name) VALUES (?,?,?)") .setParameter(1, person.getId()) .setParameter(2, person.getFirstName()) .setParameter(3, person.getLastName()) .executeUpdate(); } + + @Transactional + public void insertWithEntityManager(Person person) { + this.entityManager.persist(person); + } + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/PossessionRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/PossessionRepository.java similarity index 62% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/PossessionRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/PossessionRepository.java index f0eeb475c1..e102754c18 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/PossessionRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/PossessionRepository.java @@ -1,8 +1,9 @@ -package com.baeldung.dao.repositories.user; +package com.baeldung.boot.daos.user; -import com.baeldung.domain.user.Possession; import org.springframework.data.jpa.repository.JpaRepository; +import com.baeldung.boot.domain.Possession; + public interface PossessionRepository extends JpaRepository { } 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/boot/daos/user/UserRepository.java similarity index 52% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/UserRepository.java index 5bb0232e4a..53f692ff28 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/boot/daos/user/UserRepository.java @@ -1,6 +1,5 @@ -package com.baeldung.dao.repositories.user; +package com.baeldung.boot.daos.user; -import com.baeldung.domain.user.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -9,24 +8,30 @@ import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.baeldung.boot.domain.User; + +import java.time.LocalDate; import java.util.Collection; import java.util.List; import java.util.stream.Stream; -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository , UserRepositoryCustom{ Stream findAllByName(String name); @Query("SELECT u FROM User u WHERE u.status = 1") Collection findAllActiveUsers(); + + @Query("select u from User u where u.email like '%@gmail.com'") + List findUsersWithGmailAddress(); - @Query(value = "SELECT * FROM USERS.USERS u WHERE u.status = 1", nativeQuery = true) + @Query(value = "SELECT * FROM Users u WHERE u.status = 1", nativeQuery = true) Collection findAllActiveUsersNative(); @Query("SELECT u FROM User u WHERE u.status = ?1") User findUserByStatus(Integer status); - @Query(value = "SELECT * FROM USERS.Users u WHERE u.status = ?1", nativeQuery = true) + @Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true) User findUserByStatusNative(Integer status); @Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2") @@ -35,7 +40,7 @@ public interface UserRepository extends JpaRepository { @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name); - @Query(value = "SELECT * FROM USERS.Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true) + @Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true) User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name); @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") @@ -47,7 +52,7 @@ public interface UserRepository extends JpaRepository { @Query("SELECT u FROM User u WHERE u.name like :name%") User findUserByNameLikeNamedParam(@Param("name") String name); - @Query(value = "SELECT * FROM USERS.users u WHERE u.name LIKE ?1%", nativeQuery = true) + @Query(value = "SELECT * FROM users u WHERE u.name LIKE ?1%", nativeQuery = true) User findUserByNameLikeNative(String name); @Query(value = "SELECT u FROM User u") @@ -56,7 +61,7 @@ public interface UserRepository extends JpaRepository { @Query(value = "SELECT u FROM User u ORDER BY id") Page findAllUsersWithPagination(Pageable pageable); - @Query(value = "SELECT * FROM USERS.Users ORDER BY id", countQuery = "SELECT count(*) FROM USERS.Users", nativeQuery = true) + @Query(value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true) Page findAllUsersWithPaginationNative(Pageable pageable); @Modifying @@ -64,6 +69,31 @@ public interface UserRepository extends JpaRepository { int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name); @Modifying - @Query(value = "UPDATE USERS.Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true) + @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, active) VALUES (:name, :age, :email, :status, :active)", nativeQuery = true) + @Modifying + void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("email") String email, @Param("status") Integer status, @Param("active") boolean active); + + @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); + + 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") + int deleteDeactivatedUsers(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "alter table 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/boot/daos/user/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/UserRepositoryCustom.java new file mode 100644 index 0000000000..c586b54027 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/UserRepositoryCustom.java @@ -0,0 +1,14 @@ +package com.baeldung.boot.daos.user; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import com.baeldung.boot.domain.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/boot/daos/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/UserRepositoryCustomImpl.java new file mode 100644 index 0000000000..63a743b6b5 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/daos/user/UserRepositoryCustomImpl.java @@ -0,0 +1,57 @@ +package com.baeldung.boot.daos.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; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import com.baeldung.boot.domain.User; + +public class UserRepositoryCustomImpl implements UserRepositoryCustom { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findUserByEmails(Set emails) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(User.class); + Root user = query.from(User.class); + + Path emailPath = user.get("email"); + + List predicates = new ArrayList<>(); + for (String email : emails) { + + predicates.add(cb.like(emailPath, email)); + + } + query.select(user) + .where(cb.or(predicates.toArray(new Predicate[predicates.size()]))); + + return entityManager.createQuery(query) + .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/ddd/event/Aggregate.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate.java similarity index 95% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate.java index bf6ff0a0b9..e435f4c85c 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2.java similarity index 95% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2.java index 3d2816299a..08f61db812 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import java.util.ArrayList; import java.util.Collection; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2Repository.java similarity index 80% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2Repository.java index 2a95abe347..7f09c410fc 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate2Repository.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import org.springframework.data.repository.CrudRepository; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3.java similarity index 91% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3.java index e0c3131b06..f664322a59 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3Repository.java similarity index 83% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3Repository.java index e442bdb210..93f50bb5cf 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/Aggregate3Repository.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import org.springframework.data.repository.CrudRepository; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/AggregateRepository.java similarity index 80% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/AggregateRepository.java index 5a15156d03..1c2d3884bf 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/AggregateRepository.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import org.springframework.data.repository.CrudRepository; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DddConfig.java similarity index 89% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DddConfig.java index 1315b11875..34cf21463b 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DddConfig.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainEvent.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainEvent.java new file mode 100644 index 0000000000..e7626e742d --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainEvent.java @@ -0,0 +1,8 @@ +/** + * + */ +package com.baeldung.boot.ddd.event; + +class DomainEvent { + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainService.java similarity index 95% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainService.java index 082c9bd88e..80aa5ca6cb 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/ddd/event/DomainService.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import javax.transaction.Transactional; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Article.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Article.java similarity index 92% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Article.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Article.java index 3b5a8be088..de4dbed1a0 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Article.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Article.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.*; import java.util.Date; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Bar.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Bar.java similarity index 99% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Bar.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Bar.java index efd297bafc..35d1903801 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Bar.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Bar.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import com.google.common.collect.Sets; import org.hibernate.annotations.OrderBy; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Customer.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Customer.java new file mode 100644 index 0000000000..af88be0be6 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Customer.java @@ -0,0 +1,56 @@ +package com.baeldung.boot.domain; + +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/domain/Foo.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Foo.java similarity index 98% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Foo.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Foo.java index ef88840746..5030e5600b 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Foo.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Foo.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import org.hibernate.envers.Audited; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Item.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Item.java similarity index 97% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Item.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Item.java index 1e58fb25ba..8ac06af15a 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Item.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Item.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import java.math.BigDecimal; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/ItemType.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/ItemType.java similarity index 96% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/ItemType.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/ItemType.java index b0349e0471..8a52a9847c 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/ItemType.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/ItemType.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import java.util.ArrayList; import java.util.List; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/KVTag.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/KVTag.java similarity index 94% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/KVTag.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/KVTag.java index b3e7d78b30..1901f43c0a 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/KVTag.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/KVTag.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.Embeddable; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Location.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Location.java similarity index 96% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Location.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Location.java index 4ca7295986..9c1b93d551 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Location.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Location.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import java.util.ArrayList; import java.util.List; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.java similarity index 97% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.java index bfc690e0e2..e94c23de86 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.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-data-jpa/src/main/java/com/baeldung/domain/Person.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Person.java similarity index 95% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Person.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Person.java index 30d7370982..88894ccc72 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Person.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Person.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Possession.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Possession.java new file mode 100644 index 0000000000..f13491ad82 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Possession.java @@ -0,0 +1,83 @@ +package com.baeldung.boot.domain; + +import javax.persistence.*; +import com.baeldung.boot.domain.Possession; + +@Entity +@Table +public class Possession { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + public Possession() { + super(); + } + + public Possession(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + result = (prime * result) + ((name == null) ? 0 : name.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; + } + final Possession other = (Possession) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/SkillTag.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/SkillTag.java similarity index 93% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/SkillTag.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/SkillTag.java index 1f2778c589..0933a3e6af 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/SkillTag.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/SkillTag.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.Embeddable; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Store.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Store.java similarity index 97% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Store.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Store.java index 4172051c71..5b4b831cc7 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Store.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Store.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import java.util.ArrayList; import java.util.List; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Student.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Student.java similarity index 97% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Student.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Student.java index bd7eaeb24b..1003167cc7 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Student.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/Student.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.ElementCollection; import javax.persistence.Entity; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/User.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/User.java new file mode 100644 index 0000000000..cca00e52a2 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/domain/User.java @@ -0,0 +1,132 @@ +package com.baeldung.boot.domain; + +import javax.persistence.*; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +@Entity +@Table(name = "users") +public class User { + + @Id + @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; + private Integer status; + @OneToMany + List possessionList; + + public User() { + super(); + } + + 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() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [name=").append(name).append(", id=").append(id).append("]"); + 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/main/java/com/baeldung/passenger/CustomPassengerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java similarity index 77% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/CustomPassengerRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java index 7ae44bfbda..7152286c83 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/CustomPassengerRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.passenger; +package com.baeldung.boot.passenger; import java.util.List; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/Passenger.java similarity index 89% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/Passenger.java index 24ae47e597..c75107a783 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/Passenger.java @@ -1,4 +1,4 @@ -package com.baeldung.passenger; +package com.baeldung.boot.passenger; import javax.persistence.Basic; import javax.persistence.Column; @@ -25,15 +25,15 @@ class Passenger { @Basic(optional = false) @Column(nullable = false) - private int seatNumber; + private Integer seatNumber; - private Passenger(String firstName, String lastName, int seatNumber) { + private Passenger(String firstName, String lastName, Integer seatNumber) { this.firstName = firstName; this.lastName = lastName; this.seatNumber = seatNumber; } - static Passenger from(String firstName, String lastName, int seatNumber) { + static Passenger from(String firstName, String lastName, Integer seatNumber) { return new Passenger(firstName, lastName, seatNumber); } @@ -76,7 +76,7 @@ class Passenger { return lastName; } - int getSeatNumber() { + Integer getSeatNumber() { return seatNumber; } } 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/boot/passenger/PassengerRepository.java similarity index 75% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/PassengerRepository.java index 6ae6afb403..cdb8cc98fb 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/boot/passenger/PassengerRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.passenger; +package com.baeldung.boot.passenger; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,9 +9,14 @@ interface PassengerRepository extends JpaRepository, CustomPass Passenger findFirstByOrderBySeatNumberAsc(); + Passenger findTopByOrderBySeatNumberAsc(); + List findByOrderBySeatNumberAsc(); List findByLastNameOrderBySeatNumberAsc(String lastName); List findByLastName(String lastName, Sort sort); + + List findByFirstNameIgnoreCase(String firstName); + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java similarity index 93% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepositoryImpl.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java index bd6e535e3e..508c669066 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java @@ -1,4 +1,4 @@ -package com.baeldung.passenger; +package com.baeldung.boot.passenger; import org.springframework.stereotype.Repository; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IBarService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IBarService.java new file mode 100644 index 0000000000..8054cbba59 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IBarService.java @@ -0,0 +1,7 @@ +package com.baeldung.boot.services; + +import com.baeldung.boot.domain.Bar; + +public interface IBarService extends IOperations { + // +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IFooService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IFooService.java similarity index 76% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IFooService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IFooService.java index 7e16ace5b6..871cccdd45 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IFooService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IFooService.java @@ -1,9 +1,10 @@ -package com.baeldung.services; +package com.baeldung.boot.services; -import com.baeldung.domain.Foo; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import com.baeldung.boot.domain.Foo; + public interface IFooService extends IOperations { Foo retrieveByName(String name); diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IOperations.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IOperations.java similarity index 92% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IOperations.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IOperations.java index d50d465639..ec2b866b6f 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IOperations.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/IOperations.java @@ -1,4 +1,4 @@ -package com.baeldung.services; +package com.baeldung.boot.services; import org.springframework.data.domain.Page; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractService.java similarity index 94% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractService.java index 708524225b..8e4f643adc 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractService.java @@ -1,6 +1,6 @@ -package com.baeldung.services.impl; +package com.baeldung.boot.services.impl; -import com.baeldung.services.IOperations; +import com.baeldung.boot.services.IOperations; import com.google.common.collect.Lists; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractSpringDataJpaService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractSpringDataJpaService.java similarity index 92% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractSpringDataJpaService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractSpringDataJpaService.java index 28c86bee28..a73a6bd7fc 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/AbstractSpringDataJpaService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/AbstractSpringDataJpaService.java @@ -1,6 +1,6 @@ -package com.baeldung.services.impl; +package com.baeldung.boot.services.impl; -import com.baeldung.services.IOperations; +import com.baeldung.boot.services.IOperations; import com.google.common.collect.Lists; import org.springframework.data.repository.CrudRepository; import org.springframework.transaction.annotation.Transactional; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/BarSpringDataJpaService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/BarSpringDataJpaService.java similarity index 79% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/BarSpringDataJpaService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/BarSpringDataJpaService.java index ca3e5f868d..80568f2fd4 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/BarSpringDataJpaService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/BarSpringDataJpaService.java @@ -1,8 +1,9 @@ -package com.baeldung.services.impl; +package com.baeldung.boot.services.impl; + +import com.baeldung.boot.daos.IBarCrudRepository; +import com.baeldung.boot.domain.Bar; +import com.baeldung.boot.services.IBarService; -import com.baeldung.domain.Bar; -import com.baeldung.dao.repositories.IBarCrudRepository; -import com.baeldung.services.IBarService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.repository.CrudRepository; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/FooService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/FooService.java similarity index 87% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/FooService.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/FooService.java index 319ab3a825..04eec63854 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/impl/FooService.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/services/impl/FooService.java @@ -1,9 +1,10 @@ -package com.baeldung.services.impl; +package com.baeldung.boot.services.impl; import com.google.common.collect.Lists; -import com.baeldung.dao.IFooDao; -import com.baeldung.domain.Foo; -import com.baeldung.services.IFooService; +import com.baeldung.boot.daos.IFooDao; +import com.baeldung.boot.domain.Foo; +import com.baeldung.boot.services.IFooService; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java new file mode 100644 index 0000000000..69a1e5507e --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java @@ -0,0 +1,43 @@ +package com.baeldung.boot.web.controllers; + +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.boot.daos.CustomerRepository; +import com.baeldung.boot.domain.Customer; + +/** + * 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/dao/repositories/InsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InsertRepository.java deleted file mode 100644 index 6a74e067fe..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InsertRepository.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.dao.repositories; - -public interface InsertRepository { - void insert(S entity); -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java deleted file mode 100644 index 6d3cbb07df..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.dao.repositories; - -import com.baeldung.domain.Person; - -public interface PersonEntityManagerInsertRepository { - void insert(Person person); -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java deleted file mode 100644 index cbf3d59620..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.dao.repositories; - -import com.baeldung.domain.Person; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface PersonEntityManagerRepository extends JpaRepository, PersonEntityManagerInsertRepository { - -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java deleted file mode 100644 index be01e9883a..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.dao.repositories; - -import com.baeldung.domain.Person; - -public interface PersonQueryInsertRepository { - void insert(Person person); -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java deleted file mode 100644 index 1516c38443..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.dao.repositories; - -import com.baeldung.domain.Person; -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; - -@Repository -public interface PersonQueryRepository extends JpaRepository, PersonQueryInsertRepository { - - @Modifying - @Query(value = "INSERT INTO person (id, first_name, last_name) VALUES (:id,:firstName,:lastName)", nativeQuery = true) - void insertWithAnnotation(@Param("id") Long id, @Param("firstName") String firstName, @Param("lastName") String lastName); -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java deleted file mode 100644 index c14cc44125..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.dao.repositories.impl; - -import com.baeldung.dao.repositories.PersonEntityManagerInsertRepository; -import com.baeldung.domain.Person; -import org.springframework.transaction.annotation.Transactional; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; - -@Transactional -public class PersonEntityManagerInsertRepositoryImpl implements PersonEntityManagerInsertRepository { - - @PersistenceContext - private EntityManager entityManager; - - @Override - public void insert(Person person) { - this.entityManager.persist(person); - } -} - diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/product/ProductRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/product/ProductRepository.java deleted file mode 100755 index 1f9f5f9195..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/product/ProductRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.dao.repositories.product; - -import com.baeldung.domain.product.Product; - -import java.util.List; - -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.PagingAndSortingRepository; - -public interface ProductRepository extends PagingAndSortingRepository { - - List findAllByPrice(double price, Pageable pageable); -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java deleted file mode 100644 index 1e6479d4fc..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -package com.baeldung.ddd.event; - -class DomainEvent { - -} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java new file mode 100644 index 0000000000..3b9aa2cc18 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/MultipleDbApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.multipledb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultipleDbApplication { + + public static void main(String[] args) { + SpringApplication.run(MultipleDbApplication.class, args); + } + +} + diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java new file mode 100644 index 0000000000..a6f8f0829f --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductAutoConfiguration.java @@ -0,0 +1,71 @@ +package com.baeldung.multipledb; + +import java.util.HashMap; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * By default, the persistence-multiple-db.properties file is read for + * non auto configuration in PersistenceProductConfiguration. + *

+ * If we need to use persistence-multiple-db-boot.properties and auto configuration + * then uncomment the below @Configuration class and comment out PersistenceProductConfiguration. + */ +//@Configuration +@PropertySource({"classpath:persistence-multiple-db-boot.properties"}) +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.product", entityManagerFactoryRef = "productEntityManager", transactionManagerRef = "productTransactionManager") +@Profile("!tc") +public class PersistenceProductAutoConfiguration { + @Autowired + private Environment env; + + public PersistenceProductAutoConfiguration() { + super(); + } + + // + + @Bean + public LocalContainerEntityManagerFactoryBean productEntityManager() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(productDataSource()); + em.setPackagesToScan("com.baeldung.multipledb.model.product"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + final HashMap properties = new HashMap(); + properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); + em.setJpaPropertyMap(properties); + + return em; + } + + @Bean + @ConfigurationProperties(prefix="spring.second-datasource") + public DataSource productDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean + public PlatformTransactionManager productTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(productEntityManager().getObject()); + return transactionManager; + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceProductConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java similarity index 87% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceProductConfiguration.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java index 207fba9bc5..bcf2cd84eb 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceProductConfiguration.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceProductConfiguration.java @@ -1,9 +1,10 @@ -package com.baeldung.config; +package com.baeldung.multipledb; import com.google.common.base.Preconditions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -18,7 +19,8 @@ import java.util.HashMap; @Configuration @PropertySource({"classpath:persistence-multiple-db.properties"}) -@EnableJpaRepositories(basePackages = "com.baeldung.dao.repositories.product", entityManagerFactoryRef = "productEntityManager", transactionManagerRef = "productTransactionManager") +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.product", entityManagerFactoryRef = "productEntityManager", transactionManagerRef = "productTransactionManager") +@Profile("!tc") public class PersistenceProductConfiguration { @Autowired private Environment env; @@ -33,7 +35,7 @@ public class PersistenceProductConfiguration { public LocalContainerEntityManagerFactoryBean productEntityManager() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(productDataSource()); - em.setPackagesToScan("com.baeldung.domain.product"); + em.setPackagesToScan("com.baeldung.multipledb.model.product"); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java new file mode 100644 index 0000000000..e04a1621b2 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserAutoConfiguration.java @@ -0,0 +1,75 @@ +package com.baeldung.multipledb; + +import java.util.HashMap; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * By default, the persistence-multiple-db.properties file is read for + * non auto configuration in PersistenceUserConfiguration. + *

+ * If we need to use persistence-multiple-db-boot.properties and auto configuration + * then uncomment the below @Configuration class and comment out PersistenceUserConfiguration. + */ +//@Configuration +@PropertySource({"classpath:persistence-multiple-db-boot.properties"}) +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.user", entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager") +@Profile("!tc") +public class PersistenceUserAutoConfiguration { + @Autowired + private Environment env; + + public PersistenceUserAutoConfiguration() { + super(); + } + + // + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean userEntityManager() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(userDataSource()); + em.setPackagesToScan("com.baeldung.multipledb.model.user"); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + final HashMap properties = new HashMap(); + properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); + em.setJpaPropertyMap(properties); + + return em; + } + + @Bean + @Primary + @ConfigurationProperties(prefix="spring.datasource") + public DataSource userDataSource() { + return DataSourceBuilder.create().build(); + } + + @Primary + @Bean + public PlatformTransactionManager userTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(userEntityManager().getObject()); + return transactionManager; + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceUserConfiguration.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java similarity index 83% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceUserConfiguration.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java index dd32477755..6b48455c0c 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceUserConfiguration.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/PersistenceUserConfiguration.java @@ -1,11 +1,8 @@ -package com.baeldung.config; +package com.baeldung.multipledb; import com.google.common.base.Preconditions; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.*; import org.springframework.core.env.Environment; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.DriverManagerDataSource; @@ -19,7 +16,8 @@ import java.util.HashMap; @Configuration @PropertySource({"classpath:persistence-multiple-db.properties"}) -@EnableJpaRepositories(basePackages = "com.baeldung.dao.repositories.user", entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager") +@EnableJpaRepositories(basePackages = "com.baeldung.multipledb.dao.user", entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager") +@Profile("!tc") public class PersistenceUserConfiguration { @Autowired private Environment env; @@ -33,9 +31,10 @@ public class PersistenceUserConfiguration { @Primary @Bean public LocalContainerEntityManagerFactoryBean userEntityManager() { + System.out.println("loading config"); final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(userDataSource()); - em.setPackagesToScan("com.baeldung.domain.user"); + em.setPackagesToScan("com.baeldung.multipledb.model.user"); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java new file mode 100755 index 0000000000..022099eed0 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/product/ProductRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.multipledb.dao.product; + +import java.util.List; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; + +import com.baeldung.multipledb.model.product.ProductMultipleDB; + +public interface ProductRepository extends PagingAndSortingRepository { + + List findAllByPrice(double price, Pageable pageable); +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java new file mode 100644 index 0000000000..ae37fde20d --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/PossessionRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.multipledb.dao.user; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.multipledb.model.user.PossessionMultipleDB; + +public interface PossessionRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java new file mode 100644 index 0000000000..267a61a93f --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/dao/user/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.multipledb.dao.user; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.multipledb.model.user.UserMultipleDB; + +public interface UserRepository extends JpaRepository { +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/product/Product.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/product/ProductMultipleDB.java similarity index 76% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/product/Product.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/product/ProductMultipleDB.java index 2f82e3e318..8bdff340ac 100755 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/product/Product.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/product/ProductMultipleDB.java @@ -1,4 +1,4 @@ -package com.baeldung.domain.product; +package com.baeldung.multipledb.model.product; import javax.persistence.Entity; import javax.persistence.Id; @@ -6,7 +6,7 @@ import javax.persistence.Table; @Entity @Table(schema = "products") -public class Product { +public class ProductMultipleDB { @Id private int id; @@ -15,19 +15,19 @@ public class Product { private double price; - public Product() { + public ProductMultipleDB() { super(); } - private Product(int id, String name, double price) { + private ProductMultipleDB(int id, String name, double price) { super(); this.id = id; this.name = name; this.price = price; } - public static Product from(int id, String name, double price) { - return new Product(id, name, price); + public static ProductMultipleDB from(int id, String name, double price) { + return new ProductMultipleDB(id, name, price); } public int getId() { diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/user/PossessionMultipleDB.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/user/PossessionMultipleDB.java new file mode 100644 index 0000000000..a6a3c88bd0 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/user/PossessionMultipleDB.java @@ -0,0 +1,82 @@ +package com.baeldung.multipledb.model.user; + +import javax.persistence.*; + +@Entity +@Table +public class PossessionMultipleDB { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + public PossessionMultipleDB() { + super(); + } + + public PossessionMultipleDB(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + result = (prime * result) + ((name == null) ? 0 : name.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; + } + final PossessionMultipleDB other = (PossessionMultipleDB) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + +} 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/multipledb/model/user/UserMultipleDB.java similarity index 78% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/User.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/multipledb/model/user/UserMultipleDB.java index 3a8b617d9a..c7cd07f7a1 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/multipledb/model/user/UserMultipleDB.java @@ -1,11 +1,12 @@ -package com.baeldung.domain.user; +package com.baeldung.multipledb.model.user; import javax.persistence.*; + import java.util.List; @Entity -@Table(name = "users", schema = "users") -public class User { +@Table(name = "users") +public class UserMultipleDB { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -15,14 +16,15 @@ public class User { @Column(unique = true, nullable = false) private String email; private Integer status; + @OneToMany - List possessionList; - - public User() { + List possessionList; + + public UserMultipleDB() { super(); } - public User(String name, String email, Integer status) { + public UserMultipleDB(String name, String email, Integer status) { this.name = name; this.email = email; this.status = status; @@ -68,11 +70,11 @@ public class User { this.age = age; } - public List getPossessionList() { + public List getPossessionList() { return possessionList; } - public void setPossessionList(List possessionList) { + public void setPossessionList(List possessionList) { this.possessionList = possessionList; } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IBarService.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IBarService.java deleted file mode 100644 index 7e127488db..0000000000 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/services/IBarService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.services; - -import com.baeldung.domain.Bar; - -public interface IBarService extends IOperations { - // -} 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..f127dd5e50 100644 --- a/persistence-modules/spring-data-jpa/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa/src/main/resources/application.properties @@ -1,17 +1,6 @@ -# spring.datasource.x -spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 -spring.datasource.username=sa -spring.datasource.password=sa +spring.main.allow-bean-definition-overriding=true -# hibernate.X -hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true -hibernate.hbm2ddl.auto=create-drop -hibernate.cache.use_second_level_cache=true -hibernate.cache.use_query_cache=true -hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory - -spring.datasource.data=import_entities.sql - -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +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 diff --git a/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties b/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties new file mode 100644 index 0000000000..ffca79b3f5 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/resources/persistence-multiple-db-boot.properties @@ -0,0 +1,11 @@ +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false + +spring.datasource.jdbcUrl=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS +spring.datasource.username=sa +spring.datasource.password=sa + +spring.second-datasource.jdbcUrl=jdbc:h2:mem:spring_jpa_product;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PRODUCTS +spring.second-datasource.username=sa +spring.second-datasource.password=sa diff --git a/persistence-modules/spring-data-jpa/src/main/resources/persistence.properties b/persistence-modules/spring-data-jpa/src/main/resources/persistence.properties index 3543e1b52b..6bc83edf34 100644 --- a/persistence-modules/spring-data-jpa/src/main/resources/persistence.properties +++ b/persistence-modules/spring-data-jpa/src/main/resources/persistence.properties @@ -12,5 +12,3 @@ hibernate.cache.use_second_level_cache=true hibernate.cache.use_query_cache=true hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory -# envers.X -envers.audit_table_suffix=_audit_log \ 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..7ddf36d3f0 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/batchinserts/BatchInsertIntegrationTest.java @@ -0,0 +1,40 @@ +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.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import com.baeldung.boot.Application; +import com.baeldung.boot.daos.CustomerRepository; +import com.baeldung.boot.web.controllers.CustomerController; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes=Application.class) +@AutoConfigureMockMvc +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 diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ArticleRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java similarity index 82% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ArticleRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java index 093e744003..dfb04b3dfb 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ArticleRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java @@ -1,13 +1,16 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.daos.ArticleRepository; +import com.baeldung.boot.domain.Article; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.domain.Article; 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.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; import java.text.SimpleDateFormat; @@ -18,7 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) -@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class}) +@DataJpaTest(properties="spring.datasource.data=classpath:import_entities.sql") public class ArticleRepositoryIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ExtendedStudentRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java similarity index 80% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ExtendedStudentRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java index b19a34df82..66de5911db 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/ExtendedStudentRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java @@ -1,7 +1,10 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.daos.ExtendedStudentRepository; +import com.baeldung.boot.domain.Student; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.domain.Student; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,7 +18,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {PersistenceConfiguration.class}) +@ContextConfiguration(classes = {Application.class}) @DirtiesContext public class ExtendedStudentRepositoryIntegrationTest { @Resource diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java similarity index 85% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java index 9d6334445c..877e59d5a2 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java @@ -1,11 +1,15 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.daos.InventoryRepository; +import com.baeldung.boot.domain.MerchandiseEntity; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.domain.MerchandiseEntity; 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.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.math.BigDecimal; @@ -15,7 +19,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) -@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class}) +@SpringBootTest(classes=Application.class) public class InventoryRepositoryIntegrationTest { private static final String ORIGINAL_TITLE = "Pair of Pants"; diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java similarity index 80% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java index 01405c0b8a..30925d9b68 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.dao.repositories; +package com.baeldung.boot.daos; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertFalse; @@ -13,18 +13,24 @@ 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.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.domain.Item; -import com.baeldung.domain.ItemType; -import com.baeldung.domain.Location; -import com.baeldung.domain.Store; +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.daos.ItemTypeRepository; +import com.baeldung.boot.daos.LocationRepository; +import com.baeldung.boot.daos.ReadOnlyLocationRepository; +import com.baeldung.boot.daos.StoreRepository; +import com.baeldung.boot.domain.Item; +import com.baeldung.boot.domain.ItemType; +import com.baeldung.boot.domain.Location; +import com.baeldung.boot.domain.Store; +import com.baeldung.multipledb.PersistenceProductConfiguration; +import com.baeldung.multipledb.PersistenceUserConfiguration; @RunWith(SpringRunner.class) -@DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) +@DataJpaTest(properties="spring.datasource.data=classpath:import_entities.sql") public class JpaRepositoriesIntegrationTest { @Autowired private LocationRepository locationRepository; diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/PersonInsertRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/PersonInsertRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9d45c17035 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/PersonInsertRepositoryIntegrationTest.java @@ -0,0 +1,82 @@ +package com.baeldung.boot.daos; + +import com.baeldung.boot.daos.impl.PersonInsertRepository; +import com.baeldung.boot.domain.Person; + +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.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.persistence.EntityExistsException; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceException; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@RunWith(SpringRunner.class) +@DataJpaTest +@Import(PersonInsertRepository.class) +public class PersonInsertRepositoryIntegrationTest { + + private static final Long ID = 1L; + private static final String FIRST_NAME = "firstname"; + private static final String LAST_NAME = "lastname"; + private static final Person PERSON = new Person(ID, FIRST_NAME, LAST_NAME); + + @Autowired + private PersonInsertRepository personInsertRepository; + + @Autowired + private EntityManager entityManager; + + @Test + public void givenPersonEntity_whenInsertWithNativeQuery_ThenPersonIsPersisted() { + insertWithQuery(); + + assertPersonPersisted(); + } + + @Test + public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() { + assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> { + insertWithQuery(); + insertWithQuery(); + }); + } + + @Test + public void givenPersonEntity_whenInsertWithEntityManager_thenPersonIsPersisted() { + insertPersonWithEntityManager(); + + assertPersonPersisted(); + } + + @Test + public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() { + assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> { + insertPersonWithEntityManager(); + insertPersonWithEntityManager(); + }); + } + + private void insertWithQuery() { + personInsertRepository.insertWithQuery(PERSON); + } + + private void insertPersonWithEntityManager() { + personInsertRepository.insertWithEntityManager(new Person(ID, FIRST_NAME, LAST_NAME)); + } + + private void assertPersonPersisted() { + Person person = entityManager.find(Person.class, ID); + + assertThat(person).isNotNull(); + assertThat(person.getId()).isEqualTo(PERSON.getId()); + assertThat(person.getFirstName()).isEqualTo(PERSON.getFirstName()); + assertThat(person.getLastName()).isEqualTo(PERSON.getLastName()); + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java new file mode 100644 index 0000000000..17ee6a94ba --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryCommon.java @@ -0,0 +1,545 @@ +package com.baeldung.boot.daos; + +import org.junit.After; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.JpaSort; +import org.springframework.data.mapping.PropertyReferenceException; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.boot.daos.user.UserRepository; +import com.baeldung.boot.domain.User; + +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.*; + +public class UserRepositoryCommon { + + final String USER_EMAIL = "email@example.com"; + final String USER_EMAIL2 = "email2@example.com"; + final String USER_EMAIL3 = "email3@example.com"; + final String USER_EMAIL4 = "email4@example.com"; + final Integer INACTIVE_STATUS = 0; + final Integer ACTIVE_STATUS = 1; + 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; + @Autowired + private EntityManager entityManager; + + @Test + @Transactional + public void givenUsersWithSameNameInDB_WhenFindAllByName_ThenReturnStreamOfUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + User user4 = new User(); + user4.setName("SAMPLE"); + user4.setEmail(USER_EMAIL4); + userRepository.save(user4); + + try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { + assertThat(foundUsersStream.count()).isEqualTo(3l); + } + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotation_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsers(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotationNative_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsersNative(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotation_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatus(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotationNative_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatusNative(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationIndexedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParams(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNativeNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParamsNative(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsCustomNames_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByUserStatusAndUserName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationIndexedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLike("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNamedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNamedParam("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNative_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNative("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithSortByName_ThenReturnUsersSorted() { + 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")); + + assertThat(usersSortByName.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test(expected = PropertyReferenceException.class) + public void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() { + 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")); + + List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllSortWithFunctionQueryAnnotationJPQL_ThenReturnUsersSorted() { + 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(Sort.by("name")); + + List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationJPQL_ThenReturnPageOfUsers() { + 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(PageRequest.of(1, 3)); + + assertThat(usersPage.getContent() + .get(0) + .getName()).isEqualTo("SAMPLE1"); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationNative_ThenReturnPageOfUsers() { + 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(PageRequest.of(1, 3)); + + assertThat(usersSortByNameLength.getContent() + .get(0) + .getName()).isEqualTo(USER_NAME_PETER); + } + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationJPQL_ThenModifyMatchingUsers() { + 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"); + + assertThat(updatedUsersSize).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindByEmailsWithDynamicQuery_ThenReturnCollection() { + + User user1 = new User(); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + Set emails = new HashSet<>(); + emails.add(USER_EMAIL2); + emails.add(USER_EMAIL3); + + Collection usersWithEmails = userRepository.findUserByEmails(emails); + + assertThat(usersWithEmails.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDBWhenFindByNameListReturnCollection() { + + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + List names = Arrays.asList(USER_NAME_ADAM, USER_NAME_PETER); + + List usersWithNames = userRepository.findUserByNameList(names); + + assertThat(usersWithNames.size()).isEqualTo(2); + } + + + @Test + @Transactional + public void whenInsertedWithQuery_ThenUserIsPersisted() { + userRepository.insertUser(USER_NAME_ADAM, 1, USER_EMAIL, ACTIVE_STATUS, true); + userRepository.insertUser(USER_NAME_PETER, 1, USER_EMAIL2, ACTIVE_STATUS, true); + + 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); + } + + + @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.com", 0); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + int deletedUsersCount = userRepository.deleteDeactivatedUsers(); + + List users = userRepository.findAll(); + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + assertEquals(1, deletedUsersCount); + } + + @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 where NAME = 'usr01'"); + assertEquals(0, nativeQuery.getResultList().get(0)); + } + + @After + public void cleanUp() { + userRepository.deleteAll(); + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..1b1d264574 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryIntegrationTest.java @@ -0,0 +1,37 @@ +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.domain.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Created by adam. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@DirtiesContext +public class UserRepositoryIntegrationTest extends UserRepositoryCommon { + + @Test + @Transactional + public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeThenModifyMatchingUsers() { + 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"); + + assertThat(updatedUsersSize).isEqualTo(2); + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java new file mode 100644 index 0000000000..ab8d97bd75 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCAutoLiveTest.java @@ -0,0 +1,43 @@ +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.domain.User; +import com.baeldung.util.BaeldungPostgresqlContainer; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.PostgreSQLContainer; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Created by adam. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@ActiveProfiles({"tc", "tc-auto"}) +public class UserRepositoryTCAutoLiveTest extends UserRepositoryCommon { + + @ClassRule + public static PostgreSQLContainer postgreSQLContainer = BaeldungPostgresqlContainer.getInstance(); + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationNativePostgres_ThenModifyMatchingUsers() { + 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.updateUserSetStatusForNameNativePostgres(INACTIVE_STATUS, "SAMPLE"); + + assertThat(updatedUsersSize).isEqualTo(2); + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java new file mode 100644 index 0000000000..be8843c166 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/daos/UserRepositoryTCLiveTest.java @@ -0,0 +1,58 @@ +package com.baeldung.boot.daos; + +import com.baeldung.boot.Application; +import com.baeldung.boot.domain.User; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.PostgreSQLContainer; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@ActiveProfiles("tc") +@ContextConfiguration(initializers = {UserRepositoryTCLiveTest.Initializer.class}) +public class UserRepositoryTCLiveTest extends UserRepositoryCommon { + + @ClassRule + public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:11.1") + .withDatabaseName("integration-tests-db") + .withUsername("sa") + .withPassword("sa"); + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationNative_ThenModifyMatchingUsers() { + 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.updateUserSetStatusForNameNativePostgres(INACTIVE_STATUS, "SAMPLE"); + + assertThat(updatedUsersSize).isEqualTo(2); + } + + static class Initializer + implements ApplicationContextInitializer { + public void initialize(ConfigurableApplicationContext configurableApplicationContext) { + TestPropertyValues.of( + "spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(), + "spring.datasource.username=" + postgreSQLContainer.getUsername(), + "spring.datasource.password=" + postgreSQLContainer.getPassword() + ).applyTo(configurableApplicationContext.getEnvironment()); + } + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate2EventsIntegrationTest.java similarity index 90% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate2EventsIntegrationTest.java index 3f650d4d63..e76b932cb9 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate2EventsIntegrationTest.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; @@ -15,6 +15,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import com.baeldung.boot.ddd.event.Aggregate2; +import com.baeldung.boot.ddd.event.Aggregate2Repository; +import com.baeldung.boot.ddd.event.DomainEvent; + @SpringJUnitConfig @SpringBootTest class Aggregate2EventsIntegrationTest { diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate3EventsIntegrationTest.java similarity index 90% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate3EventsIntegrationTest.java index 893dcac3f8..4193e932ee 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/Aggregate3EventsIntegrationTest.java @@ -1,7 +1,7 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; @@ -14,6 +14,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import com.baeldung.boot.ddd.event.Aggregate3; +import com.baeldung.boot.ddd.event.Aggregate3Repository; +import com.baeldung.boot.ddd.event.DomainEvent; + @SpringJUnitConfig @SpringBootTest class Aggregate3EventsIntegrationTest { diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java similarity index 91% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java index f0e1147245..ac607063b2 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/AggregateEventsIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; @@ -16,6 +16,11 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import com.baeldung.boot.ddd.event.Aggregate; +import com.baeldung.boot.ddd.event.AggregateRepository; +import com.baeldung.boot.ddd.event.DomainEvent; +import com.baeldung.boot.ddd.event.DomainService; + @SpringJUnitConfig @SpringBootTest class AggregateEventsIntegrationTest { diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/TestEventHandler.java similarity index 68% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/TestEventHandler.java index 721402c17a..0f499834eb 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/ddd/event/TestEventHandler.java @@ -1,10 +1,12 @@ /** * */ -package com.baeldung.ddd.event; +package com.baeldung.boot.ddd.event; import org.springframework.transaction.event.TransactionalEventListener; +import com.baeldung.boot.ddd.event.DomainEvent; + interface TestEventHandler { @TransactionalEventListener void handleEvent(DomainEvent event); diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java new file mode 100644 index 0000000000..f082350019 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java @@ -0,0 +1,190 @@ +package com.baeldung.boot.passenger; + +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.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.boot.passenger.Passenger; +import com.baeldung.boot.passenger.PassengerRepository; + +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 { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private PassengerRepository repository; + + @Before + public void before() { + entityManager.persist(Passenger.from("Jill", "Smith", 50)); + entityManager.persist(Passenger.from("Eve", "Jackson", 95)); + entityManager.persist(Passenger.from("Fred", "Bloggs", 22)); + entityManager.persist(Passenger.from("Ricki", "Bobbie", 36)); + entityManager.persist(Passenger.from("Siya", "Kolisi", 85)); + } + + @Test + public void givenSeveralPassengersWhenOrderedBySeatNumberLimitedToThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + List passengers = repository.findOrderedBySeatNumberLimitedTo(1); + + assertEquals(1, passengers.size()); + + Passenger actual = passengers.get(0); + assertEquals(expected, actual); + } + + @Test + public void givenSeveralPassengersWhenFindFirstByOrderBySeatNumberAscThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + Passenger actual = repository.findFirstByOrderBySeatNumberAsc(); + + assertEquals(expected, actual); + } + + @Test + public void givenSeveralPassengersWhenFindPageSortedByThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + Page page = repository.findAll(PageRequest.of(0, 1, + Sort.by(Sort.Direction.ASC, "seatNumber"))); + + assertEquals(1, page.getContent().size()); + + Passenger actual = page.getContent().get(0); + assertEquals(expected, actual); + } + + @Test + public void givenPassengers_whenOrderedBySeatNumberAsc_thenCorrectOrder() { + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + + List passengers = repository.findByOrderBySeatNumberAsc(); + + assertThat(passengers, contains(fred, ricki, jill, siya, eve)); + } + + @Test + public void givenPassengers_whenFindAllWithSortBySeatNumberAsc_thenCorrectOrder() { + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + + List passengers = repository.findAll(Sort.by(Sort.Direction.ASC, "seatNumber")); + + assertThat(passengers, contains(fred, ricki, jill, siya, eve)); + } + + @Test + public void givenPassengers_whenFindByExampleDefaultMatcher_thenExpectedReturned() { + Example example = Example.of(Passenger.from("Fred", "Bloggs", null)); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); + } + + @Test + public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() { + ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase(); + Example example = Example.of(Passenger.from("fred", "bloggs", null), + caseInsensitiveExampleMatcher); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); + } + + @Test + public void givenPassengers_whenFindByExampleCustomMatcher_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); + + ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny().withMatcher("firstName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()).withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()); + + Example example = Example.of(Passenger.from("e", "s", null), + customExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(jill, eve, fred, siya)); + assertThat(passengers, not(contains(ricki))); + } + + @Test + public void givenPassengers_whenFindByIgnoringMatcher_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); + + ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); + + Example example = Example.of(Passenger.from(null, "b", null), + 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))); + + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/AbstractServicePersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/AbstractServicePersistenceIntegrationTest.java similarity index 98% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/AbstractServicePersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/AbstractServicePersistenceIntegrationTest.java index acac66f2f7..bf0c85fca6 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/AbstractServicePersistenceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/AbstractServicePersistenceIntegrationTest.java @@ -1,6 +1,7 @@ -package com.baeldung.services; +package com.baeldung.boot.services; -import com.baeldung.domain.Foo; +import com.baeldung.boot.domain.Foo; +import com.baeldung.boot.services.IOperations; import com.baeldung.util.IDUtil; import org.hamcrest.Matchers; import org.junit.Ignore; diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/FooServicePersistenceIntegrationTest.java similarity index 85% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/FooServicePersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/FooServicePersistenceIntegrationTest.java index fd17d033e1..f0e4aa7317 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/FooServicePersistenceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/FooServicePersistenceIntegrationTest.java @@ -1,11 +1,16 @@ -package com.baeldung.services; +package com.baeldung.boot.services; + +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.domain.Foo; +import com.baeldung.boot.services.IFooService; +import com.baeldung.boot.services.IOperations; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.domain.Foo; import org.junit.Ignore; 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.dao.DataIntegrityViolationException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.test.context.ContextConfiguration; @@ -16,7 +21,7 @@ import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {PersistenceConfiguration.class}, loader = AnnotationConfigContextLoader.class) +@SpringBootTest(classes=Application.class) public class FooServicePersistenceIntegrationTest extends AbstractServicePersistenceIntegrationTest { @Autowired diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/SpringDataJPABarAuditIntegrationTest.java similarity index 87% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/SpringDataJPABarAuditIntegrationTest.java index f3b857c73d..810cf70769 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/boot/services/SpringDataJPABarAuditIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.services; +package com.baeldung.boot.services; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -16,16 +16,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.domain.Bar; +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.boot.domain.Bar; +import com.baeldung.boot.services.IBarService; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { PersistenceConfiguration.class }, loader = AnnotationConfigContextLoader.class) +@SpringBootTest(classes=Application.class) public class SpringDataJPABarAuditIntegrationTest { private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class); diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java deleted file mode 100644 index 476554f6d6..0000000000 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.baeldung.dao.repositories; - -import com.baeldung.domain.Person; -import org.junit.Test; -import org.junit.jupiter.api.BeforeEach; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@RunWith(SpringRunner.class) -@DataJpaTest -public class PersonInsertRepositoryIntegrationTest { - - private static final Long ID = 1L; - private static final String FIRST_NAME = "firstname"; - private static final String LAST_NAME = "lastname"; - private static final Person PERSON = new Person(ID, FIRST_NAME, LAST_NAME); - - @Autowired - private PersonQueryRepository personQueryRepository; - - @Autowired - private PersonEntityManagerRepository personEntityManagerRepository; - - @BeforeEach - public void clearDB() { - personQueryRepository.deleteAll(); - } - - @Test - public void givenPersonEntity_whenInsertWithNativeQuery_ThenPersonIsPersisted() { - insertPerson(); - - assertPersonPersisted(); - } - - @Test - public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenDataIntegrityViolationExceptionIsThrown() { - assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> { - insertPerson(); - insertPerson(); - }); - } - - @Test - public void givenPersonEntity_whenInsertWithQueryAnnotation_thenPersonIsPersisted() { - insertPersonWithQueryAnnotation(); - - assertPersonPersisted(); - } - - @Test - public void givenPersonEntity_whenInsertedTwiceWithQueryAnnotation_thenDataIntegrityViolationExceptionIsThrown() { - assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> { - insertPersonWithQueryAnnotation(); - insertPersonWithQueryAnnotation(); - }); - } - - @Test - public void givenPersonEntity_whenInsertWithEntityManager_thenPersonIsPersisted() { - insertPersonWithEntityManager(); - - assertPersonPersisted(); - } - - @Test - public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenDataIntegrityViolationExceptionIsThrown() { - assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> { - insertPersonWithEntityManager(); - insertPersonWithEntityManager(); - }); - } - - private void insertPerson() { - personQueryRepository.insert(PERSON); - } - - private void insertPersonWithQueryAnnotation() { - personQueryRepository.insertWithAnnotation(ID, FIRST_NAME, LAST_NAME); - } - - private void insertPersonWithEntityManager() { - personEntityManagerRepository.insert(new Person(ID, FIRST_NAME, LAST_NAME)); - } - - private void assertPersonPersisted() { - Optional personOptional = personQueryRepository.findById(PERSON.getId()); - - assertThat(personOptional.isPresent()).isTrue(); - assertThat(personOptional.get().getId()).isEqualTo(PERSON.getId()); - assertThat(personOptional.get().getFirstName()).isEqualTo(PERSON.getFirstName()); - assertThat(personOptional.get().getLastName()).isEqualTo(PERSON.getLastName()); - } -} 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/UserRepositoryIntegrationTest.java deleted file mode 100644 index e29161394b..0000000000 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java +++ /dev/null @@ -1,378 +0,0 @@ -package com.baeldung.dao.repositories; - -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.context.SpringBootTest; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.jpa.domain.JpaSort; -import org.springframework.data.mapping.PropertyReferenceException; -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.List; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Created by adam. - */ -@RunWith(SpringRunner.class) -@SpringBootTest(classes = PersistenceConfiguration.class) -@DirtiesContext -public class UserRepositoryIntegrationTest { - - private final String USER_NAME_ADAM = "Adam"; - private final String USER_NAME_PETER = "Peter"; - - private final String USER_EMAIL = "email@example.com"; - private final String USER_EMAIL2 = "email2@example.com"; - private final String USER_EMAIL3 = "email3@example.com"; - private final String USER_EMAIL4 = "email4@example.com"; - private final String USER_EMAIL5 = "email5@example.com"; - private final String USER_EMAIL6 = "email6@example.com"; - - private final Integer INACTIVE_STATUS = 0; - private final Integer ACTIVE_STATUS = 1; - - @Autowired - private UserRepository userRepository; - - @Test - @Transactional - public void givenUsersWithSameNameInDBWhenFindAllByNameThenReturnStreamOfUsers() { - User user1 = new User(); - user1.setName(USER_NAME_ADAM); - user1.setEmail(USER_EMAIL); - userRepository.save(user1); - - User user2 = new User(); - user2.setName(USER_NAME_ADAM); - user2.setEmail(USER_EMAIL2); - userRepository.save(user2); - - User user3 = new User(); - user3.setName(USER_NAME_ADAM); - user3.setEmail(USER_EMAIL3); - userRepository.save(user3); - - User user4 = new User(); - user4.setName("SAMPLE"); - user4.setEmail(USER_EMAIL4); - userRepository.save(user4); - - try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { - assertThat(foundUsersStream.count()).isEqualTo(3l); - } - } - - @Test - public void givenUsersInDBWhenFindAllWithQueryAnnotationThenReturnCollectionWithActiveUsers() { - User user1 = new User(); - user1.setName(USER_NAME_ADAM); - user1.setEmail(USER_EMAIL); - user1.setStatus(ACTIVE_STATUS); - userRepository.save(user1); - - User user2 = new User(); - user2.setName(USER_NAME_ADAM); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User user3 = new User(); - user3.setName(USER_NAME_ADAM); - user3.setEmail(USER_EMAIL3); - user3.setStatus(INACTIVE_STATUS); - userRepository.save(user3); - - Collection allActiveUsers = userRepository.findAllActiveUsers(); - - assertThat(allActiveUsers.size()).isEqualTo(2); - } - - @Test - public void givenUsersInDBWhenFindAllWithQueryAnnotationNativeThenReturnCollectionWithActiveUsers() { - User user1 = new User(); - user1.setName(USER_NAME_ADAM); - user1.setEmail(USER_EMAIL); - user1.setStatus(ACTIVE_STATUS); - userRepository.save(user1); - - User user2 = new User(); - user2.setName(USER_NAME_ADAM); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User user3 = new User(); - user3.setName(USER_NAME_ADAM); - user3.setEmail(USER_EMAIL3); - user3.setStatus(INACTIVE_STATUS); - userRepository.save(user3); - - Collection allActiveUsers = userRepository.findAllActiveUsersNative(); - - assertThat(allActiveUsers.size()).isEqualTo(2); - } - - @Test - public void givenUserInDBWhenFindUserByStatusWithQueryAnnotationThenReturnActiveUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User userByStatus = userRepository.findUserByStatus(ACTIVE_STATUS); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUserInDBWhenFindUserByStatusWithQueryAnnotationNativeThenReturnActiveUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User userByStatus = userRepository.findUserByStatusNative(ACTIVE_STATUS); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByStatusAndNameWithQueryAnnotationIndexedParamsThenReturnOneUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User user2 = new User(); - user2.setName(USER_NAME_PETER); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User userByStatus = userRepository.findUserByStatusAndName(ACTIVE_STATUS, USER_NAME_ADAM); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsThenReturnOneUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User user2 = new User(); - user2.setName(USER_NAME_PETER); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User userByStatus = userRepository.findUserByStatusAndNameNamedParams(ACTIVE_STATUS, USER_NAME_ADAM); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByStatusAndNameWithQueryAnnotationNativeNamedParamsThenReturnOneUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User user2 = new User(); - user2.setName(USER_NAME_PETER); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User userByStatus = userRepository.findUserByStatusAndNameNamedParamsNative(ACTIVE_STATUS, USER_NAME_ADAM); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsCustomNamesThenReturnOneUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User user2 = new User(); - user2.setName(USER_NAME_PETER); - user2.setEmail(USER_EMAIL2); - user2.setStatus(ACTIVE_STATUS); - userRepository.save(user2); - - User userByStatus = userRepository.findUserByUserStatusAndUserName(ACTIVE_STATUS, USER_NAME_ADAM); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByNameLikeWithQueryAnnotationIndexedParamsThenReturnUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User userByStatus = userRepository.findUserByNameLike("Ad"); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByNameLikeWithQueryAnnotationNamedParamsThenReturnUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User userByStatus = userRepository.findUserByNameLikeNamedParam("Ad"); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @Test - public void givenUsersInDBWhenFindUserByNameLikeWithQueryAnnotationNativeThenReturnUser() { - User user = new User(); - user.setName(USER_NAME_ADAM); - user.setEmail(USER_EMAIL); - user.setStatus(ACTIVE_STATUS); - userRepository.save(user); - - User userByStatus = userRepository.findUserByNameLikeNative("Ad"); - - assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); - } - - @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)); - - List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); - - assertThat(usersSortByName - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); - } - - @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.findAll(new Sort(Sort.Direction.ASC, "name")); - - List usersSortByNameLength = userRepository.findAll(new Sort("LENGTH(name)")); - - assertThat(usersSortByNameLength - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); - } - - @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.findAllUsers(new Sort("name")); - - List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); - - assertThat(usersSortByNameLength - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); - } - - @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)); - - Page usersPage = userRepository.findAllUsersWithPagination(new PageRequest(1, 3)); - - assertThat(usersPage - .getContent() - .get(0) - .getName()).isEqualTo("SAMPLE1"); - } - - @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)); - - Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(new PageRequest(1, 3)); - - assertThat(usersSortByNameLength - .getContent() - .get(0) - .getName()).isEqualTo("SAMPLE1"); - } - - @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)); - - int updatedUsersSize = userRepository.updateUserSetStatusForName(INACTIVE_STATUS, "SAMPLE"); - - assertThat(updatedUsersSize).isEqualTo(2); - } - - @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.flush(); - - int updatedUsersSize = userRepository.updateUserSetStatusForNameNative(INACTIVE_STATUS, "SAMPLE"); - - assertThat(updatedUsersSize).isEqualTo(2); - } - - @After - public void cleanUp() { - userRepository.deleteAll(); - } - -} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java similarity index 72% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java index 71a3fb0b44..6ba10a4d49 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/JpaMultipleDBIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.services; +package com.baeldung.multipledb; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -10,26 +10,22 @@ import java.util.Optional; 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.dao.DataIntegrityViolationException; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.dao.repositories.product.ProductRepository; -import com.baeldung.dao.repositories.user.PossessionRepository; -import com.baeldung.dao.repositories.user.UserRepository; -import com.baeldung.domain.product.Product; -import com.baeldung.domain.user.Possession; -import com.baeldung.domain.user.User; +import com.baeldung.multipledb.dao.product.ProductRepository; +import com.baeldung.multipledb.dao.user.PossessionRepository; +import com.baeldung.multipledb.dao.user.UserRepository; +import com.baeldung.multipledb.model.product.ProductMultipleDB; +import com.baeldung.multipledb.model.user.PossessionMultipleDB; +import com.baeldung.multipledb.model.user.UserMultipleDB; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) +@SpringBootTest(classes=MultipleDbApplication.class) @EnableTransactionManagement -@DirtiesContext public class JpaMultipleDBIntegrationTest { @Autowired @@ -46,15 +42,15 @@ public class JpaMultipleDBIntegrationTest { @Test @Transactional("userTransactionManager") public void whenCreatingUser_thenCreated() { - User user = new User(); + UserMultipleDB user = new UserMultipleDB(); user.setName("John"); user.setEmail("john@test.com"); user.setAge(20); - Possession p = new Possession("sample"); + PossessionMultipleDB p = new PossessionMultipleDB("sample"); p = possessionRepository.save(p); user.setPossessionList(Collections.singletonList(p)); user = userRepository.save(user); - final Optional result = userRepository.findById(user.getId()); + final Optional result = userRepository.findById(user.getId()); assertTrue(result.isPresent()); System.out.println(result.get().getPossessionList()); assertEquals(1, result.get().getPossessionList().size()); @@ -63,14 +59,14 @@ public class JpaMultipleDBIntegrationTest { @Test @Transactional("userTransactionManager") public void whenCreatingUsersWithSameEmail_thenRollback() { - User user1 = new User(); + UserMultipleDB user1 = new UserMultipleDB(); user1.setName("John"); user1.setEmail("john@test.com"); user1.setAge(20); user1 = userRepository.save(user1); assertTrue(userRepository.findById(user1.getId()).isPresent()); - User user2 = new User(); + UserMultipleDB user2 = new UserMultipleDB(); user2.setName("Tom"); user2.setEmail("john@test.com"); user2.setAge(10); @@ -88,7 +84,7 @@ public class JpaMultipleDBIntegrationTest { @Test @Transactional("productTransactionManager") public void whenCreatingProduct_thenCreated() { - Product product = new Product(); + ProductMultipleDB product = new ProductMultipleDB(); product.setName("Book"); product.setId(2); product.setPrice(20); diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/product/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java similarity index 69% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/product/ProductRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java index 4caa0f0ca4..2c965f72f3 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/product/ProductRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/multipledb/ProductRepositoryIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.dao.repositories.product; +package com.baeldung.multipledb; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; @@ -13,6 +13,7 @@ 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.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -22,11 +23,12 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.domain.product.Product; +import com.baeldung.multipledb.PersistenceProductConfiguration; +import com.baeldung.multipledb.dao.product.ProductRepository; +import com.baeldung.multipledb.model.product.ProductMultipleDB; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { PersistenceProductConfiguration.class }) +@SpringBootTest(classes=MultipleDbApplication.class) @EnableTransactionManagement public class ProductRepositoryIntegrationTest { @@ -36,22 +38,22 @@ public class ProductRepositoryIntegrationTest { @Before @Transactional("productTransactionManager") public void setUp() { - productRepository.save(Product.from(1001, "Book", 21)); - productRepository.save(Product.from(1002, "Coffee", 10)); - productRepository.save(Product.from(1003, "Jeans", 30)); - productRepository.save(Product.from(1004, "Shirt", 32)); - productRepository.save(Product.from(1005, "Bacon", 10)); + productRepository.save(ProductMultipleDB.from(1001, "Book", 21)); + productRepository.save(ProductMultipleDB.from(1002, "Coffee", 10)); + productRepository.save(ProductMultipleDB.from(1003, "Jeans", 30)); + productRepository.save(ProductMultipleDB.from(1004, "Shirt", 32)); + productRepository.save(ProductMultipleDB.from(1005, "Bacon", 10)); } @Test public void whenRequestingFirstPageOfSizeTwo_ThenReturnFirstPage() { Pageable pageRequest = PageRequest.of(0, 2); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(2)); assertTrue(result.stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .allMatch(id -> Arrays.asList(1001, 1002) .contains(id))); } @@ -60,11 +62,11 @@ public class ProductRepositoryIntegrationTest { public void whenRequestingSecondPageOfSizeTwo_ThenReturnSecondPage() { Pageable pageRequest = PageRequest.of(1, 2); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(2)); assertTrue(result.stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .allMatch(id -> Arrays.asList(1003, 1004) .contains(id))); } @@ -73,11 +75,11 @@ public class ProductRepositoryIntegrationTest { public void whenRequestingLastPage_ThenReturnLastPageWithRemData() { Pageable pageRequest = PageRequest.of(2, 2); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(1)); assertTrue(result.stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .allMatch(id -> Arrays.asList(1005) .contains(id))); } @@ -86,12 +88,12 @@ public class ProductRepositoryIntegrationTest { public void whenSortingByNameAscAndPaging_ThenReturnSortedPagedResult() { Pageable pageRequest = PageRequest.of(0, 3, Sort.by("name")); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(3)); assertThat(result.getContent() .stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .collect(Collectors.toList()), equalTo(Arrays.asList(1005, 1001, 1002))); } @@ -101,12 +103,12 @@ public class ProductRepositoryIntegrationTest { Pageable pageRequest = PageRequest.of(0, 3, Sort.by("price") .descending()); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(3)); assertThat(result.getContent() .stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .collect(Collectors.toList()), equalTo(Arrays.asList(1004, 1003, 1001))); } @@ -117,12 +119,12 @@ public class ProductRepositoryIntegrationTest { .descending() .and(Sort.by("name"))); - Page result = productRepository.findAll(pageRequest); + Page result = productRepository.findAll(pageRequest); assertThat(result.getContent(), hasSize(5)); assertThat(result.getContent() .stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .collect(Collectors.toList()), equalTo(Arrays.asList(1004, 1003, 1001, 1005, 1002))); } @@ -131,11 +133,11 @@ public class ProductRepositoryIntegrationTest { public void whenRequestingFirstPageOfSizeTwoUsingCustomMethod_ThenReturnFirstPage() { Pageable pageRequest = PageRequest.of(0, 2); - List result = productRepository.findAllByPrice(10, pageRequest); + List result = productRepository.findAllByPrice(10, pageRequest); assertThat(result, hasSize(2)); assertTrue(result.stream() - .map(Product::getId) + .map(ProductMultipleDB::getId) .allMatch(id -> Arrays.asList(1002, 1005) .contains(id))); } 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 deleted file mode 100644 index c57e771345..0000000000 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.baeldung.passenger; - -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.data.domain.Page; -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 static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertEquals; - -@DataJpaTest -@RunWith(SpringRunner.class) -public class PassengerRepositoryIntegrationTest { - - @PersistenceContext - private EntityManager entityManager; - @Autowired - private PassengerRepository repository; - - @Before - public void before() { - entityManager.persist(Passenger.from("Jill", "Smith", 50)); - entityManager.persist(Passenger.from("Eve", "Jackson", 95)); - entityManager.persist(Passenger.from("Fred", "Bloggs", 22)); - entityManager.persist(Passenger.from("Ricki", "Bobbie", 36)); - entityManager.persist(Passenger.from("Siya", "Kolisi", 85)); - } - - @Test - public void givenSeveralPassengersWhenOrderedBySeatNumberLimitedToThenThePassengerInTheFirstFilledSeatIsReturned() { - Passenger expected = Passenger.from("Fred", "Bloggs", 22); - - List passengers = repository.findOrderedBySeatNumberLimitedTo(1); - - assertEquals(1, passengers.size()); - - Passenger actual = passengers.get(0); - assertEquals(actual, expected); - } - - @Test - public void givenSeveralPassengersWhenFindFirstByOrderBySeatNumberAscThenThePassengerInTheFirstFilledSeatIsReturned() { - Passenger expected = Passenger.from("Fred", "Bloggs", 22); - - Passenger actual = repository.findFirstByOrderBySeatNumberAsc(); - - assertEquals(actual, expected); - } - - @Test - public void givenSeveralPassengersWhenFindPageSortedByThenThePassengerInTheFirstFilledSeatIsReturned() { - Passenger expected = Passenger.from("Fred", "Bloggs", 22); - - Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber"))); - - assertEquals(page.getContent().size(), 1); - - Passenger actual = page.getContent().get(0); - assertEquals(expected, actual); - } - - @Test - public void givenPassengers_whenOrderedBySeatNumberAsc_thenCorrectOrder() { - Passenger fred = Passenger.from("Fred", "Bloggs", 22); - Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); - Passenger jill = Passenger.from("Jill", "Smith", 50); - Passenger siya = Passenger.from("Siya", "Kolisi", 85); - Passenger eve = Passenger.from("Eve", "Jackson", 95); - - List passengers = repository.findByOrderBySeatNumberAsc(); - - assertThat(passengers, contains(fred, ricki, jill, siya, eve)); - } - - @Test - public void givenPassengers_whenFindAllWithSortBySeatNumberAsc_thenCorrectOrder() { - Passenger fred = Passenger.from("Fred", "Bloggs", 22); - Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); - Passenger jill = Passenger.from("Jill", "Smith", 50); - Passenger siya = Passenger.from("Siya", "Kolisi", 85); - Passenger eve = Passenger.from("Eve", "Jackson", 95); - - List passengers = repository.findAll(Sort.by(Sort.Direction.ASC, "seatNumber")); - - assertThat(passengers, contains(fred, ricki, jill, siya, eve)); - } - -} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/util/BaeldungPostgresqlContainer.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/util/BaeldungPostgresqlContainer.java new file mode 100644 index 0000000000..e5ad2dd448 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/util/BaeldungPostgresqlContainer.java @@ -0,0 +1,35 @@ +package com.baeldung.util; + +import org.testcontainers.containers.PostgreSQLContainer; + +public class BaeldungPostgresqlContainer extends PostgreSQLContainer { + + private static final String IMAGE_VERSION = "postgres:11.1"; + + private static BaeldungPostgresqlContainer container; + + + private BaeldungPostgresqlContainer() { + super(IMAGE_VERSION); + } + + public static BaeldungPostgresqlContainer getInstance() { + if (container == null) { + container = new BaeldungPostgresqlContainer(); + } + return container; + } + + @Override + public void start() { + super.start(); + System.setProperty("DB_URL", container.getJdbcUrl()); + System.setProperty("DB_USERNAME", container.getUsername()); + System.setProperty("DB_PASSWORD", container.getPassword()); + } + + @Override + public void stop() { + //do nothing, JVM handles shut down + } +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 7f906bdbcd..e885d0fe51 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -5,7 +5,7 @@ import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.Application; +import com.baeldung.boot.Application; @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) diff --git a/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringJpaContextIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringJpaContextIntegrationTest.java index 66b5b20b97..4a36407884 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringJpaContextIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/org/baeldung/SpringJpaContextIntegrationTest.java @@ -6,10 +6,10 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.Application; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; +import com.baeldung.boot.Application; +import com.baeldung.boot.config.PersistenceConfiguration; +import com.baeldung.multipledb.PersistenceProductConfiguration; +import com.baeldung.multipledb.PersistenceUserConfiguration; @RunWith(SpringRunner.class) @DataJpaTest(excludeAutoConfiguration = { diff --git a/persistence-modules/spring-data-jpa/src/test/resources/application-tc-auto.properties b/persistence-modules/spring-data-jpa/src/test/resources/application-tc-auto.properties new file mode 100644 index 0000000000..c3005d861f --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/resources/application-tc-auto.properties @@ -0,0 +1,4 @@ +# configuration for test containers testing +spring.datasource.url=${DB_URL} +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} diff --git a/persistence-modules/spring-data-jpa/src/test/resources/application-tc.properties b/persistence-modules/spring-data-jpa/src/test/resources/application-tc.properties new file mode 100644 index 0000000000..3bf8693d53 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/resources/application-tc.properties @@ -0,0 +1,4 @@ +# configuration for Test Containers testing +spring.datasource.driver-class-name=org.postgresql.Driver +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml index 76ec5a96a6..33ad3a5267 100644 --- a/persistence-modules/spring-data-mongodb/pom.xml +++ b/persistence-modules/spring-data-mongodb/pom.xml @@ -1,9 +1,7 @@ 4.0.0 - com.baeldung spring-data-mongodb - 0.0.1-SNAPSHOT spring-data-mongodb @@ -23,9 +21,8 @@ org.springframework.data spring-data-releasetrain - Lovelace-M3 + Lovelace-SR9 pom - import @@ -76,17 +73,6 @@ - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - @@ -109,10 +95,9 @@ - 2.1.2.RELEASE + 2.1.9.RELEASE 4.1.4 1.1.3 - 5.1.0.RELEASE 1.9.2 3.2.0.RELEASE diff --git a/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml b/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml index 324f7f60c2..d59ebcef6e 100644 --- a/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml +++ b/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml @@ -7,33 +7,32 @@ http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context.xsd" -> - - + http://www.springframework.org/schema/context/spring-context.xsd"> + + - + - + - + - + - + - + \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java index 1da50d7cb4..1002dc79eb 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java @@ -44,6 +44,12 @@ import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class ZipsAggregationLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java index 3a88a1e654..d25b9ece4f 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java @@ -31,6 +31,12 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.client.gridfs.model.GridFSFile; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @ContextConfiguration("file:src/main/resources/mongoConfig.xml") @RunWith(SpringJUnit4ClassRunner.class) public class GridFSLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java index d05bde0f1b..e5e4a188ec 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java @@ -24,6 +24,12 @@ import com.baeldung.config.MongoConfig; import com.baeldung.model.EmailAddress; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class DocumentQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java index 309f14e995..9e12997c67 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java @@ -16,6 +16,12 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SimpleMongoConfig.class) public class MongoTemplateProjectionLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java index fc78921b75..4f62f0d7a7 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java @@ -27,6 +27,12 @@ import com.baeldung.config.MongoConfig; import com.baeldung.model.EmailAddress; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class MongoTemplateQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java index 096015ca0a..79648f1a20 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java @@ -15,6 +15,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.time.ZoneOffset; import java.time.ZonedDateTime; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class ActionRepositoryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java index e4849181e5..c94bb2ae4c 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java @@ -7,6 +7,12 @@ import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ public class BaseQueryLiveTest { @Autowired diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java index f87ca5cbb5..0ccf677b3e 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java @@ -15,8 +15,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.querydsl.core.types.Predicate; - - +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class DSLQueryLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java index 4e99c0b140..3a99407350 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java @@ -12,6 +12,12 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class JSONQueryLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java index 47e67a6b4c..ef8ce10dd1 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java @@ -12,6 +12,12 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class QueryMethodsLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java index 901610e42d..dd7215af7e 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java @@ -23,6 +23,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.config.MongoConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class UserRepositoryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java index 80f4275794..8972246041 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java @@ -13,6 +13,12 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class UserRepositoryProjectionLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java similarity index 90% rename from persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java rename to persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java index 43aa865e91..3fc8dcf977 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java @@ -12,9 +12,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.config.MongoReactiveConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoReactiveConfig.class) -public class MongoTransactionReactiveIntegrationTest { +public class MongoTransactionReactiveLiveTest { @Autowired private ReactiveMongoOperations reactiveOps; diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java similarity index 94% rename from persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java rename to persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java index 1dbe724d87..53b2c7a0e7 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java @@ -24,9 +24,15 @@ import org.springframework.transaction.support.TransactionTemplate; import com.baeldung.config.MongoConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) -public class MongoTransactionTemplateIntegrationTest { +public class MongoTransactionTemplateLiveTest { @Autowired private MongoTemplate mongoTemplate; diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java similarity index 95% rename from persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java rename to persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java index 4d747789a0..bafcd770ec 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java @@ -24,10 +24,16 @@ import com.baeldung.model.User; import com.baeldung.repository.UserRepository; import com.mongodb.MongoCommandException; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class MongoTransactionalIntegrationTest { +public class MongoTransactionalLiveTest { @Autowired private MongoTemplate mongoTemplate; diff --git a/persistence-modules/spring-data-redis/pom.xml b/persistence-modules/spring-data-redis/pom.xml index fb80b0413f..4ae8ac0a87 100644 --- a/persistence-modules/spring-data-redis/pom.xml +++ b/persistence-modules/spring-data-redis/pom.xml @@ -79,6 +79,21 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + true + true + -Xmx1024m + + + + + 3.2.4 2.9.0 diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsIntegrationTest.java index e48aa1e06a..1333f94653 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsIntegrationTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsIntegrationTest.java @@ -2,6 +2,9 @@ package com.baeldung.spring.data.reactive.redis.template; import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication; + +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -9,22 +12,40 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.connection.ReactiveKeyCommands; import org.springframework.data.redis.connection.ReactiveStringCommands; import org.springframework.data.redis.connection.ReactiveStringCommands.SetCommand; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit4.SpringRunner; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import redis.embedded.RedisServerBuilder; +import java.io.IOException; import java.nio.ByteBuffer; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class RedisKeyCommandsIntegrationTest { + + private static redis.embedded.RedisServer redisServer; @Autowired private ReactiveKeyCommands keyCommands; @Autowired private ReactiveStringCommands stringCommands; + + @BeforeClass + public static void startRedisServer() throws IOException { + redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build(); + redisServer.start(); + } + + @AfterClass + public static void stopRedisServer() throws IOException { + redisServer.stop(); + } @Test public void givenFluxOfKeys_whenPerformOperations_thenPerformOperations() { diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsIntegrationTest.java index 3ebeff87b1..88c4fa6eed 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsIntegrationTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsIntegrationTest.java @@ -2,27 +2,48 @@ package com.baeldung.spring.data.reactive.redis.template; import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication; + +import java.io.IOException; + +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; 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.redis.core.ReactiveListOperations; import org.springframework.data.redis.core.ReactiveRedisTemplate; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit4.SpringRunner; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import redis.embedded.RedisServerBuilder; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class RedisTemplateListOpsIntegrationTest { private static final String LIST_NAME = "demo_list"; + private static redis.embedded.RedisServer redisServer; @Autowired private ReactiveRedisTemplate redisTemplate; private ReactiveListOperations reactiveListOps; + + @BeforeClass + public static void startRedisServer() throws IOException { + redisServer = new RedisServerBuilder().port(6379).setting("maxheap 128M").build(); + redisServer.start(); + } + + @AfterClass + public static void stopRedisServer() throws IOException { + redisServer.stop(); + } @Before public void setup() { diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsIntegrationTest.java index 9490568089..afa5267582 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsIntegrationTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsIntegrationTest.java @@ -1,29 +1,51 @@ package com.baeldung.spring.data.reactive.redis.template; -import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication; -import com.baeldung.spring.data.reactive.redis.model.Employee; +import java.io.IOException; +import java.time.Duration; + +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; 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.redis.core.ReactiveRedisTemplate; import org.springframework.data.redis.core.ReactiveValueOperations; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication; +import com.baeldung.spring.data.reactive.redis.model.Employee; + import reactor.core.publisher.Mono; import reactor.test.StepVerifier; - -import java.time.Duration; +import redis.embedded.RedisServerBuilder; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class RedisTemplateValueOpsIntegrationTest { + + private static redis.embedded.RedisServer redisServer; @Autowired private ReactiveRedisTemplate redisTemplate; private ReactiveValueOperations reactiveValueOps; + + @BeforeClass + public static void startRedisServer() throws IOException { + redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build(); + redisServer.start(); + } + + @AfterClass + public static void stopRedisServer() throws IOException { + redisServer.stop(); + } @Before public void setup() { diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java index 99febb6430..1c69b63c09 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerIntegrationTest.java @@ -19,9 +19,11 @@ import com.baeldung.spring.data.redis.config.RedisConfig; import com.baeldung.spring.data.redis.queue.RedisMessagePublisher; import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber; +import redis.embedded.RedisServerBuilder; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = RedisConfig.class) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class RedisMessageListenerIntegrationTest { private static redis.embedded.RedisServer redisServer; @@ -31,7 +33,7 @@ public class RedisMessageListenerIntegrationTest { @BeforeClass public static void startRedisServer() throws IOException { - redisServer = new redis.embedded.RedisServer(6380); + redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build(); redisServer.start(); } diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java index 43aadefc01..b1a36475c3 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryIntegrationTest.java @@ -20,9 +20,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.data.redis.config.RedisConfig; import com.baeldung.spring.data.redis.model.Student; +import redis.embedded.RedisServerBuilder; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = RedisConfig.class) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class StudentRepositoryIntegrationTest { @Autowired @@ -32,7 +34,7 @@ public class StudentRepositoryIntegrationTest { @BeforeClass public static void startRedisServer() throws IOException { - redisServer = new redis.embedded.RedisServer(6380); + redisServer = new RedisServerBuilder().port(6379).setting("maxheap 128M").build(); redisServer.start(); } diff --git a/persistence-modules/spring-data-solr/pom.xml b/persistence-modules/spring-data-solr/pom.xml index dcba80b49a..82539b0ca8 100644 --- a/persistence-modules/spring-data-solr/pom.xml +++ b/persistence-modules/spring-data-solr/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-data-solr 0.0.1-SNAPSHOT - jar spring-data-solr + jar com.baeldung diff --git a/persistence-modules/spring-hibernate-3/pom.xml b/persistence-modules/spring-hibernate-3/pom.xml index 6c1bdace30..ec35f35bb3 100644 --- a/persistence-modules/spring-hibernate-3/pom.xml +++ b/persistence-modules/spring-hibernate-3/pom.xml @@ -91,7 +91,6 @@ 3.6.10.Final 5.1.40 8.5.8 - 1.4.193 19.0 3.5 diff --git a/persistence-modules/spring-hibernate-5/README.md b/persistence-modules/spring-hibernate-5/README.md index 75d23f7532..dfcc4e7eb8 100644 --- a/persistence-modules/spring-hibernate-5/README.md +++ b/persistence-modules/spring-hibernate-5/README.md @@ -1,6 +1,6 @@ ### Relevant articles -- [@Immutable in Hibernate](http://www.baeldung.com/hibernate-immutable) - [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) +- [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search) diff --git a/persistence-modules/spring-hibernate-5/pom.xml b/persistence-modules/spring-hibernate-5/pom.xml index 832cf8dca7..16e55cb0c0 100644 --- a/persistence-modules/spring-hibernate-5/pom.xml +++ b/persistence-modules/spring-hibernate-5/pom.xml @@ -143,7 +143,6 @@ 9.0.0.M26 1.1 2.3.4 - 1.4.195 21.0 diff --git a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java index 723b097305..31877255b2 100644 --- a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java +++ b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java @@ -1,24 +1,31 @@ package com.baeldung.hibernate.criteria; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; - +import static org.junit.Assert.assertFalse; import java.util.List; import org.hibernate.Session; +import org.hibernate.Transaction; import org.junit.Test; import com.baeldung.hibernate.criteria.model.Item; import com.baeldung.hibernate.criteria.util.HibernateUtil; import com.baeldung.hibernate.criteria.view.ApplicationView; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.criteria.Root; + public class HibernateCriteriaIntegrationTest { final private ApplicationView av = new ApplicationView(); @Test public void testPerformanceOfCriteria() { - assertTrue(av.checkIfCriteriaTimeLower()); + assertFalse(av.checkIfCriteriaTimeLower()); } @Test @@ -179,4 +186,51 @@ public class HibernateCriteriaIntegrationTest { session.close(); assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria()); } + + @Test + public void givenNewItemPrice_whenCriteriaUpdate_thenReturnAffectedResult() { + + int oldPrice = 10, newPrice = 20; + + Session session = HibernateUtil.getHibernateSession(); + + Item item = new Item(12, "Test Item 12", "This is a description"); + item.setItemPrice(oldPrice); + session.save(item); + + CriteriaBuilder cb = session.getCriteriaBuilder(); + CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class); + Root root = criteriaUpdate.from(Item.class); + criteriaUpdate.set("itemPrice", newPrice); + criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice)); + + Transaction transaction = session.beginTransaction(); + session.createQuery(criteriaUpdate).executeUpdate(); + transaction.commit(); + + Item updatedItem = session.createQuery("FROM Item WHERE itemPrice = " + newPrice, Item.class).getSingleResult(); + session.refresh(updatedItem); + assertEquals(newPrice, updatedItem.getItemPrice().intValue()); + } + + @Test + public void givenTargetItemPrice_whenCriteriaDelete_thenDeleteMatched() { + + int targetPrice = 1000; + + Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder cb = session.getCriteriaBuilder(); + CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class); + Root root = criteriaDelete.from(Item.class); + criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice)); + + Transaction transaction = session.beginTransaction(); + session.createQuery(criteriaDelete).executeUpdate(); + transaction.commit(); + + List deletedItem = session.createQuery("FROM Item WHERE itemPrice > " + targetPrice, Item.class).list(); + assertTrue(deletedItem.isEmpty()); + + } + } diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index b15b7278f4..6f8d83aa9d 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -3,16 +3,13 @@ ## Spring with Hibernate 4 Example Project ### Relevant Articles: -- [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) +- [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) - [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) -- [Auditing with JPA, Hibernate, and Spring Data JPA](http://www.baeldung.com/database-auditing-jpa) - [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial) - [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate) - [Eager/Lazy Loading In Hibernate](http://www.baeldung.com/hibernate-lazy-eager-loading) - [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many) -- [Guide to @Immutable Annotation in Hibernate](http://www.baeldung.com/hibernate-immutable) - [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) ### Quick Start diff --git a/persistence-modules/spring-hibernate4/pom.xml b/persistence-modules/spring-hibernate4/pom.xml index fad84870df..4289c9c3d5 100644 --- a/persistence-modules/spring-hibernate4/pom.xml +++ b/persistence-modules/spring-hibernate4/pom.xml @@ -160,7 +160,6 @@ 8.5.8 1.1 2.3.4 - 1.4.193 5.3.3.Final diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateManyisOwningSide.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateManyisOwningSide.java new file mode 100644 index 0000000000..372fb2fc07 --- /dev/null +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateManyisOwningSide.java @@ -0,0 +1,71 @@ +package com.baeldung.hibernate.oneToMany.main; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil; +import com.baeldung.hibernate.oneToMany.model.Cart; +import com.baeldung.hibernate.oneToMany.model.Items; +import com.baeldung.hibernate.oneToMany.model.ItemsOIO; + +public class HibernateManyisOwningSide { + public static void main(String[] args) { + + Cart cart = new Cart(); + Cart cart2 = new Cart(); + + Items item1 = new Items(cart); + Items item2 = new Items(cart2); + Set itemsSet = new HashSet(); + itemsSet.add(item1); + itemsSet.add(item2); + + cart.setItems(itemsSet); + + + + SessionFactory sessionFactory = null; + Session session = null; + Transaction tx = null; + try { + // Get Session + sessionFactory = HibernateAnnotationUtil.getSessionFactory(); + session = sessionFactory.getCurrentSession(); + System.out.println("Session created"); + // start transaction + tx = session.beginTransaction(); + // Save the Model object + session.save(cart); + session.save(cart2); + session.save(item1); + session.save(item2); + // Commit transaction + tx.commit(); + session = sessionFactory.getCurrentSession(); + tx = session.beginTransaction(); + + item1 = (Items) session.get(Items.class, new Long(1)); + item2 = (Items) session.get(Items.class, new Long(2)); + tx.commit(); + + + System.out.println("item1 ID=" + item1.getId() + ", Foreign Key CartOIO ID=" + item1.getCart() + .getId()); + System.out.println("item2 ID=" + item2.getId() + ", Foreign Key CartOIO ID=" + item2.getCart() + .getId()); + + } catch (Exception e) { + System.out.println("Exception occured. " + e.getMessage()); + e.printStackTrace(); + } finally { + if (!sessionFactory.isClosed()) { + System.out.println("Closing SessionFactory"); + sessionFactory.close(); + } + } + } +} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneisOwningSide.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneisOwningSide.java new file mode 100644 index 0000000000..0777664dd0 --- /dev/null +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneisOwningSide.java @@ -0,0 +1,67 @@ +package com.baeldung.hibernate.oneToMany.main; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import com.baeldung.hibernate.oneToMany.config.HibernateAnnotationUtil; +import com.baeldung.hibernate.oneToMany.model.CartOIO; +import com.baeldung.hibernate.oneToMany.model.ItemsOIO; + +public class HibernateOneisOwningSide { + public static void main(String[] args) { + + CartOIO cart = new CartOIO(); + CartOIO cart2 = new CartOIO(); + + ItemsOIO item1 = new ItemsOIO(cart); + ItemsOIO item2 = new ItemsOIO(cart2); + Set itemsSet = new HashSet(); + itemsSet.add(item1); + itemsSet.add(item2); + + cart.setItems(itemsSet); + + SessionFactory sessionFactory = null; + Session session = null; + Transaction tx = null; + try { + // Get Session + sessionFactory = HibernateAnnotationUtil.getSessionFactory(); + session = sessionFactory.getCurrentSession(); + System.out.println("Session created"); + // start transaction + tx = session.beginTransaction(); + // Save the Model object + session.save(cart); + session.save(cart2); + session.save(item1); + session.save(item2); + // Commit transaction + tx.commit(); + + session = sessionFactory.getCurrentSession(); + tx = session.beginTransaction(); + item1 = (ItemsOIO) session.get(ItemsOIO.class, new Long(1)); + item2 = (ItemsOIO) session.get(ItemsOIO.class, new Long(2)); + tx.commit(); + + System.out.println("item1 ID=" + item1.getId() + ", Foreign Key CartOIO ID=" + item1.getCartOIO() + .getId()); + System.out.println("item2 ID=" + item2.getId() + ", Foreign Key CartOIO ID=" + item2.getCartOIO() + .getId()); + + } catch (Exception e) { + System.out.println("Exception occured. " + e.getMessage()); + e.printStackTrace(); + } finally { + if (!sessionFactory.isClosed()) { + System.out.println("Closing SessionFactory"); + sessionFactory.close(); + } + } + } +} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/CartOIO.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/CartOIO.java new file mode 100644 index 0000000000..8a5ed5e7a4 --- /dev/null +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/CartOIO.java @@ -0,0 +1,42 @@ +package com.baeldung.hibernate.oneToMany.model; + +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.Table; + + + +@Entity +@Table(name = "CARTOIO") +public class CartOIO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @OneToMany + @JoinColumn(name = "cart_id") // we need to duplicate the physical information + private Set items; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Set getItems() { + return items; + } + + public void setItems(Set items) { + this.items = items; + } + +} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/ItemsOIO.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/ItemsOIO.java new file mode 100644 index 0000000000..a3d6a796c5 --- /dev/null +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/ItemsOIO.java @@ -0,0 +1,47 @@ +package com.baeldung.hibernate.oneToMany.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "ITEMSOIO") +public class ItemsOIO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @ManyToOne + @JoinColumn(name = "cart_id", insertable = false, updatable = false) + private CartOIO cart; + + // Hibernate requires no-args constructor + public ItemsOIO() { + } + + public ItemsOIO(CartOIO c) { + this.cart = c; + } + + public CartOIO getCartOIO() { + return cart; + } + + public void setCartOIO(CartOIO cart) { + this.cart = cart; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + +} diff --git a/persistence-modules/spring-hibernate4/src/main/resources/hibernate-annotation.cfg.xml b/persistence-modules/spring-hibernate4/src/main/resources/hibernate-annotation.cfg.xml index 311300c77c..14d853d3fd 100644 --- a/persistence-modules/spring-hibernate4/src/main/resources/hibernate-annotation.cfg.xml +++ b/persistence-modules/spring-hibernate4/src/main/resources/hibernate-annotation.cfg.xml @@ -9,11 +9,13 @@ jdbc:mysql://localhost:3306/spring_hibernate_one_to_many?createDatabaseIfNotExist=true myuser org.hibernate.dialect.MySQLDialect - + create thread true + + diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index e6f91ac016..e856e4808e 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -4,8 +4,6 @@ ### Relevant Articles: -- [Spring 3 and JPA with Hibernate](http://www.baeldung.com/2011/12/13/the-persistence-layer-with-spring-3-1-and-jpa/) -- [Transactions with Spring 3 and JPA](http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/) - [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa) - [JPA Pagination](http://www.baeldung.com/jpa-pagination) - [Sorting with JPA](http://www.baeldung.com/jpa-sort) @@ -15,12 +13,12 @@ - [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) - [Many-To-Many Relationship in JPA](https://www.baeldung.com/jpa-many-to-many) + ### Eclipse Config After importing the project into Eclipse, you may see the following error: "No persistence xml file found in project" diff --git a/persistence-modules/spring-jpa/pom.xml b/persistence-modules/spring-jpa/pom.xml index 400811b582..0fdffad8db 100644 --- a/persistence-modules/spring-jpa/pom.xml +++ b/persistence-modules/spring-jpa/pom.xml @@ -3,8 +3,8 @@ 4.0.0 spring-jpa 0.1-SNAPSHOT - war spring-jpa + war com.baeldung @@ -93,7 +93,7 @@ javax.servlet jstl - ${javax.servlet.jstl.version} + ${jstl.version} javax.servlet @@ -156,21 +156,19 @@ - 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 - 1.4.195 + 2.1.5.RELEASE - 1.2 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 new file mode 100644 index 0000000000..822cbb8ed5 --- /dev/null +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,21 @@ +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; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfigL2Cache.class }, loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +@DirtiesContext +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} 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()); } diff --git a/persistence-modules/spring-persistence-simple/.gitignore b/persistence-modules/spring-persistence-simple/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/.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/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md new file mode 100644 index 0000000000..8e55a59c7c --- /dev/null +++ b/persistence-modules/spring-persistence-simple/README.md @@ -0,0 +1,24 @@ +========= + +## Spring Persistence Example Project + + +### Relevant Articles: +- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa) +- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring) +- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) +- [Simplify the DAO with Spring and Java Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics) +- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) +- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) +- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) +- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) + +### 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-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml new file mode 100644 index 0000000000..1afacab164 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -0,0 +1,154 @@ + + 4.0.0 + spring-persistence-simple + 0.1-SNAPSHOT + spring-persistence-simple + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + + org.springframework + spring-orm + ${org.springframework.version} + + + org.springframework + spring-context + ${org.springframework.version} + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + javax.transaction + jta + ${jta.version} + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + runtime + + + org.springframework.data + spring-data-jpa + ${spring-data-jpa.version} + + + com.h2database + h2 + ${h2.version} + + + + org.apache.tomcat + tomcat-dbcp + ${tomcat-dbcp.version} + + + + + + com.google.guava + guava + ${guava.version} + + + org.assertj + assertj-core + ${assertj.version} + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + test + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + com.querydsl + querydsl-jpa + ${querydsl.version} + + + com.querydsl + querydsl-apt + ${querydsl.version} + + + + + spring-persistence-simple + + + src/main/resources + true + + + + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + generate-sources + + process + + + target/generated-sources + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + + + + 5.1.6.RELEASE + + + 5.4.2.Final + 6.0.6 + 2.1.6.RELEASE + 9.0.0.M26 + 1.1 + 4.2.1 + + + 21.0 + 3.5 + 3.8.0 + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceConfiguration.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java similarity index 64% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceConfiguration.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java index 2bdd4e5451..569971e311 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/config/PersistenceConfiguration.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java @@ -4,6 +4,7 @@ import java.util.Properties; import javax.sql.DataSource; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -13,7 +14,8 @@ import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -21,31 +23,40 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl; -import com.baeldung.services.IBarService; -import com.baeldung.services.impl.BarSpringDataJpaService; +import com.baeldung.hibernate.dao.FooDao; +import com.baeldung.jpa.dao.IFooDao; import com.google.common.base.Preconditions; @Configuration -@ComponentScan({ "com.baeldung.dao", "com.baeldung.services" }) @EnableTransactionManagement -@EnableJpaRepositories(basePackages = { "com.baeldung.dao" }, repositoryBaseClass = ExtendedRepositoryImpl.class) +@EnableJpaRepositories(basePackages = { "com.baeldung.hibernate.dao" }, transactionManagerRef = "jpaTransactionManager") @EnableJpaAuditing -@PropertySource("classpath:persistence.properties") -public class PersistenceConfiguration { +@PropertySource({ "classpath:persistence-mysql.properties" }) +@ComponentScan({ "com.baeldung.persistence", "com.baeldung.hibernate.dao" }) +public class PersistenceConfig { @Autowired private Environment env; - public PersistenceConfiguration() { + public PersistenceConfig() { super(); } + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); - emf.setDataSource(dataSource()); - emf.setPackagesToScan("com.baeldung.domain"); + emf.setDataSource(restDataSource()); + emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); emf.setJpaVendorAdapter(vendorAdapter); @@ -55,8 +66,8 @@ public class PersistenceConfiguration { } @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); @@ -66,7 +77,14 @@ public class PersistenceConfiguration { } @Bean - public PlatformTransactionManager transactionManager() { + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PlatformTransactionManager jpaTransactionManager() { final JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); return transactionManager; @@ -78,8 +96,8 @@ public class PersistenceConfiguration { } @Bean - public IBarService barSpringDataJpaService() { - return new BarSpringDataJpaService(); + public IFooDao fooHibernateDao() { + return new FooDao(); } private final Properties hibernateProperties() { @@ -92,8 +110,7 @@ public class PersistenceConfiguration { // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); // Envers properties - hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", - env.getProperty("envers.audit_table_suffix")); + hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); return hibernateProperties; } diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java new file mode 100644 index 0000000000..9fae34d99e --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java @@ -0,0 +1,87 @@ +package com.baeldung.config; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +@ComponentScan({ "com.baeldung.persistence","com.baeldung.jpa.dao" }) +@EnableJpaRepositories(basePackages = "com.baeldung.jpa.dao") +public class PersistenceJPAConfig { + + @Autowired + private Environment env; + + public PersistenceJPAConfig() { + super(); + } + + // beans + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(emf); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false"); + + + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java new file mode 100644 index 0000000000..5fc932b256 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java @@ -0,0 +1,39 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class BarHibernateDAO { + + @Autowired + private SessionFactory sessionFactory; + + public TestEntity findEntity(int id) { + + return getCurrentSession().find(TestEntity.class, 1); + } + + public void createEntity(TestEntity entity) { + + getCurrentSession().save(entity); + } + + public void createEntity(int id, String newDescription) { + + TestEntity entity = findEntity(id); + entity.setDescription(newDescription); + getCurrentSession().save(entity); + } + + public void deleteEntity(int id) { + + TestEntity entity = findEntity(id); + getCurrentSession().delete(entity); + } + + protected Session getCurrentSession() { + return sessionFactory.getCurrentSession(); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java new file mode 100644 index 0000000000..150e3778af --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java @@ -0,0 +1,61 @@ +package com.baeldung.hibernate.bootstrap; + +import com.google.common.base.Preconditions; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +public class HibernateConf { + + @Autowired + private Environment env; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(dataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate.bootstrap.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource dataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + return hibernateProperties; + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java new file mode 100644 index 0000000000..b3e979478f --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java @@ -0,0 +1,24 @@ +package com.baeldung.hibernate.bootstrap; + +import com.google.common.base.Preconditions; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@ImportResource({ "classpath:hibernate5Configuration.xml" }) +public class HibernateXMLConf { + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java new file mode 100644 index 0000000000..cae41db831 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java @@ -0,0 +1,29 @@ +package com.baeldung.hibernate.bootstrap.model; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class TestEntity { + + private int id; + + private String description; + + @Id + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java new file mode 100644 index 0000000000..67c10fe7fe --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/dao/FooDao.java @@ -0,0 +1,20 @@ +package com.baeldung.hibernate.dao; + +import com.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +import com.baeldung.jpa.dao.IFooDao; +import com.baeldung.persistence.dao.common.AbstractHibernateDao; + +@Repository +public class FooDao extends AbstractHibernateDao implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java similarity index 88% rename from spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java index 8a02fe6a53..48ddfb04b1 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/CustomSQLErrorCodeTranslator.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/CustomSQLErrorCodeTranslator.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.SQLException; @@ -10,7 +10,7 @@ public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTransl @Override protected DataAccessException customTranslate(final String task, final String sql, final SQLException sqlException) { - if (sqlException.getErrorCode() == -104) { + if (sqlException.getErrorCode() == 23505) { return new DuplicateKeyException("Custome Exception translator - Integrity contraint voilation.", sqlException); } return null; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/Employee.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java similarity index 96% rename from spring-all/src/main/java/org/baeldung/jdbc/Employee.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java index e9408eb7fa..a43eb265c7 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/Employee.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/Employee.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; public class Employee { private int id; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java similarity index 99% rename from spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index 1f0e7b28ad..9ba4ebdb6d 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.PreparedStatement; import java.sql.SQLException; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java similarity index 95% rename from spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java index f926836c40..d09cd45dbc 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/EmployeeRowMapper.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/EmployeeRowMapper.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java similarity index 84% rename from spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java index f7eb592366..ddc24e439f 100644 --- a/spring-all/src/main/java/org/baeldung/jdbc/config/SpringJdbcConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jdbc/config/SpringJdbcConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.jdbc.config; +package com.baeldung.jdbc.config; import javax.sql.DataSource; @@ -10,12 +10,12 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @Configuration -@ComponentScan("org.baeldung.jdbc") +@ComponentScan("com.baeldung.jdbc") public class SpringJdbcConfig { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build(); } // @Bean diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java new file mode 100644 index 0000000000..4fbc8464bb --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java @@ -0,0 +1,47 @@ +package com.baeldung.jpa.dao; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +public abstract class AbstractJpaDAO { + + private Class clazz; + + @PersistenceContext + private EntityManager entityManager; + + public final void setClazz(final Class clazzToSet) { + this.clazz = clazzToSet; + } + + public T findOne(final long id) { + return entityManager.find(clazz, id); + } + + @SuppressWarnings("unchecked") + public List findAll() { + return entityManager.createQuery("from " + clazz.getName()).getResultList(); + } + + public T create(final T entity) { + entityManager.persist(entity); + return entity; + } + + public T update(final T entity) { + return entityManager.merge(entity); + } + + public void delete(final T entity) { + entityManager.remove(entity); + } + + public void deleteById(final long entityId) { + final T entity = findOne(entityId); + delete(entity); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java new file mode 100644 index 0000000000..e79a44a0c2 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/FooDao.java @@ -0,0 +1,17 @@ +package com.baeldung.jpa.dao; + +import com.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +@Repository +public class FooDao extends AbstractJpaDAO implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java new file mode 100644 index 0000000000..8140c56edd --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/IFooDao.java @@ -0,0 +1,21 @@ +package com.baeldung.jpa.dao; + +import java.util.List; + +import com.baeldung.persistence.model.Foo; + +public interface IFooDao { + + Foo findOne(long id); + + List findAll(); + + Foo create(Foo entity); + + Foo update(Foo entity); + + void delete(Foo entity); + + void deleteById(long entityId); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java new file mode 100644 index 0000000000..5a6c76a93a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import com.google.common.base.Preconditions; + +public abstract class AbstractDao implements IOperations { + + protected Class clazz; + + protected final void setClazz(final Class clazzToSet) { + clazz = Preconditions.checkNotNull(clazzToSet); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java new file mode 100644 index 0000000000..e406f896dc --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java @@ -0,0 +1,60 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.base.Preconditions; + +@SuppressWarnings("unchecked") +public abstract class AbstractHibernateDao extends AbstractDao implements IOperations { + + @Autowired + protected SessionFactory sessionFactory; + + // API + + @Override + public T findOne(final long id) { + return (T) getCurrentSession().get(clazz, id); + } + + @Override + public List findAll() { + return getCurrentSession().createQuery("from " + clazz.getName()).list(); + } + + @Override + public T create(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().saveOrUpdate(entity); + return entity; + } + + @Override + public T update(final T entity) { + Preconditions.checkNotNull(entity); + return (T) getCurrentSession().merge(entity); + } + + @Override + public void delete(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + final T entity = findOne(entityId); + Preconditions.checkState(entity != null); + delete(entity); + } + + protected Session getCurrentSession() { + return sessionFactory.getCurrentSession(); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java new file mode 100644 index 0000000000..18b16fa033 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java @@ -0,0 +1,13 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +@Repository +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao { + // +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java new file mode 100644 index 0000000000..d4da194f4d --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java @@ -0,0 +1,15 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +import com.baeldung.jpa.dao.AbstractJpaDAO; + +@Repository +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class GenericJpaDao extends AbstractJpaDAO implements IGenericDao { + // +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java new file mode 100644 index 0000000000..8d8af18394 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java @@ -0,0 +1,7 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +public interface IGenericDao extends IOperations { + // +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java new file mode 100644 index 0000000000..34c5e0f616 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java @@ -0,0 +1,20 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +public interface IOperations { + + T findOne(final long id); + + List findAll(); + + T create(final T entity); + + T update(final T entity); + + void delete(final T entity); + + void deleteById(final long entityId); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java new file mode 100644 index 0000000000..5a88ecc6cf --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Bar.java @@ -0,0 +1,102 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; + +@Entity +public class Bar implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + @OneToMany(mappedBy = "bar", fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @OrderBy("name ASC") + List fooList; + + public Bar() { + super(); + } + + public Bar(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public List getFooList() { + return fooList; + } + + public void setFooList(final List fooList) { + this.fooList = fooList; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Bar other = (Bar) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Bar [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java new file mode 100644 index 0000000000..009876f8cb --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/model/Foo.java @@ -0,0 +1,104 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Cacheable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedNativeQueries; +import javax.persistence.NamedNativeQuery; + +import org.hibernate.annotations.CacheConcurrencyStrategy; + +@Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) }) +public class Foo implements Serializable { + + private static final long serialVersionUID = 1L; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID") + private Long id; + @Column(name = "NAME") + private String name; + + @ManyToOne(targetEntity = Bar.class, fetch = FetchType.EAGER) + @JoinColumn(name = "BAR_ID") + private Bar bar; + + public Bar getBar() { + return bar; + } + + public void setBar(final Bar bar) { + this.bar = bar; + } + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java new file mode 100644 index 0000000000..efe9743670 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/service/FooService.java @@ -0,0 +1,36 @@ +package com.baeldung.persistence.service; + +import java.util.List; + +import com.baeldung.jpa.dao.IFooDao; +import com.baeldung.persistence.model.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class FooService { + + @Autowired + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + public void create(final Foo entity) { + dao.create(entity); + } + + public Foo findOne(final long id) { + return dao.findOne(id); + } + + public List findAll() { + return dao.findAll(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java new file mode 100644 index 0000000000..717b9c3aa0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/config/PersistenceConfig.java @@ -0,0 +1,85 @@ +package com.baeldung.spring.data.persistence.config; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" }) +@ComponentScan({ "com.baeldung.spring.data.persistence" }) +// @ImportResource("classpath*:springDataPersistenceConfig.xml") +@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.dao") +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.spring.data.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + // vendorAdapter.set + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..d2b746dc8b --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/IFooDao.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.data.persistence.dao; + +import com.baeldung.spring.data.persistence.model.Foo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +public interface IFooDao extends JpaRepository { + + @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") + Foo retrieveByName(@Param("name") String name); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java new file mode 100644 index 0000000000..e8f95302ef --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepository.java @@ -0,0 +1,98 @@ +package com.baeldung.spring.data.persistence.dao.user; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +import com.baeldung.spring.data.persistence.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +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; + +public interface UserRepository extends JpaRepository, UserRepositoryCustom { + + Stream findAllByName(String name); + + @Query("SELECT u FROM User u WHERE u.status = 1") + Collection findAllActiveUsers(); + + @Query("select u from User u where u.email like '%@gmail.com'") + List findUsersWithGmailAddress(); + + @Query(value = "SELECT * FROM Users u WHERE u.status = 1", nativeQuery = true) + Collection findAllActiveUsersNative(); + + @Query("SELECT u FROM User u WHERE u.status = ?1") + User findUserByStatus(Integer status); + + @Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true) + User findUserByStatusNative(Integer status); + + @Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2") + User findUserByStatusAndName(Integer status, String name); + + @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") + User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name); + + @Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true) + User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name); + + @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") + User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName); + + @Query("SELECT u FROM User u WHERE u.name like ?1%") + User findUserByNameLike(String name); + + @Query("SELECT u FROM User u WHERE u.name like :name%") + User findUserByNameLikeNamedParam(@Param("name") String name); + + @Query(value = "SELECT * FROM users u WHERE u.name LIKE ?1%", nativeQuery = true) + User findUserByNameLikeNative(String name); + + @Query(value = "SELECT u FROM User u") + List findAllUsers(Sort sort); + + @Query(value = "SELECT u FROM User u ORDER BY id") + Page findAllUsersWithPagination(Pageable pageable); + + @Query(value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true) + Page findAllUsersWithPaginationNative(Pageable pageable); + + @Modifying + @Query("update User u set u.status = :status where u.name = :name") + int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name); + + @Modifying + @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, active) VALUES (:name, :age, :email, :status, :active)", nativeQuery = true) + @Modifying + void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("email") String email, @Param("status") Integer status, @Param("active") boolean active); + + @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); + + 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") + int deleteDeactivatedUsers(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true) + void addDeletedColumn(); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java new file mode 100644 index 0000000000..ff92159077 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.data.persistence.dao.user; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import com.baeldung.spring.data.persistence.model.User; + +public interface UserRepositoryCustom { + List findUserByEmails(Set emails); + + List findAllUsersByPredicates(Collection> predicates); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java new file mode 100644 index 0000000000..8bd8217e83 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.data.persistence.dao.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; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import com.baeldung.spring.data.persistence.model.User; + +public class UserRepositoryCustomImpl implements UserRepositoryCustom { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findUserByEmails(Set emails) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(User.class); + Root user = query.from(User.class); + + Path emailPath = user.get("email"); + + List predicates = new ArrayList<>(); + for (String email : emails) { + + predicates.add(cb.like(emailPath, email)); + + } + query.select(user) + .where(cb.or(predicates.toArray(new Predicate[predicates.size()]))); + + return entityManager.createQuery(query) + .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-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java new file mode 100644 index 0000000000..64bfe203d0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Foo.java @@ -0,0 +1,83 @@ +package com.baeldung.spring.data.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/Possession.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java similarity index 96% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/Possession.java rename to persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java index 614e13df36..44ca9fc62e 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/Possession.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/Possession.java @@ -1,4 +1,4 @@ -package com.baeldung.domain.user; +package com.baeldung.spring.data.persistence.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -7,7 +7,7 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(schema = "users") +@Table public class Possession { @Id diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java new file mode 100644 index 0000000000..09f1092644 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/model/User.java @@ -0,0 +1,132 @@ +package com.baeldung.spring.data.persistence.model; + +import javax.persistence.*; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +@Entity +@Table(name = "users") +public class User { + + @Id + @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; + private Integer status; + @OneToMany + List possessionList; + + public User() { + super(); + } + + 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() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [name=").append(name).append(", id=").append(id).append("]"); + 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-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java new file mode 100644 index 0000000000..00e7ac01e4 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/IFooService.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.data.persistence.service; + +import com.baeldung.spring.data.persistence.model.Foo; + +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooService extends IOperations { + + Foo retrieveByName(String name); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java new file mode 100644 index 0000000000..61c7d6fcaa --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/common/AbstractService.java @@ -0,0 +1,56 @@ +package com.baeldung.spring.data.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.persistence.dao.common.IOperations; +import com.google.common.collect.Lists; + +@Transactional +public abstract class AbstractService implements IOperations { + + // read - one + + @Override + @Transactional(readOnly = true) + public T findOne(final long id) { + return getDao().findById(id).orElse(null); + } + + // read - all + + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + + // write + + @Override + public T create(final T entity) { + return getDao().save(entity); + } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(long entityId) { + T entity = findOne(entityId); + delete(entity); + } + + protected abstract PagingAndSortingRepository getDao(); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java new file mode 100644 index 0000000000..cd566ba9f6 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/spring/data/persistence/service/impl/FooService.java @@ -0,0 +1,38 @@ +package com.baeldung.spring.data.persistence.service.impl; + + +import com.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.spring.data.persistence.dao.IFooDao; +import com.baeldung.spring.data.persistence.service.IFooService; +import com.baeldung.spring.data.persistence.service.common.AbstractService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class FooService extends AbstractService implements IFooService { + + @Autowired + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + @Override + protected PagingAndSortingRepository getDao() { + return dao; + } + + // custom methods + + @Override + public Foo retrieveByName(final String name) { + return dao.retrieveByName(name); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java new file mode 100644 index 0000000000..45e72e046d --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/util/IDUtil.java @@ -0,0 +1,33 @@ +package com.baeldung.util; + +import java.util.Random; + +public final class IDUtil { + + private IDUtil() { + throw new AssertionError(); + } + + // API + + public static String randomPositiveLongAsString() { + return Long.toString(randomPositiveLong()); + } + + public static String randomNegativeLongAsString() { + return Long.toString(randomNegativeLong()); + } + + public static long randomPositiveLong() { + long id = new Random().nextLong() * 10000; + id = (id < 0) ? (-1 * id) : id; + return id; + } + + private static long randomNegativeLong() { + long id = new Random().nextLong() * 10000; + id = (id > 0) ? (-1 * id) : id; + return id; + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml new file mode 100644 index 0000000000..bbb61cb3e0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml new file mode 100644 index 0000000000..cb6cf0aa5c --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql new file mode 100644 index 0000000000..c86d35cdae --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE EMPLOYEE +( + ID int NOT NULL PRIMARY KEY, + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + ADDRESS varchar(255), +); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml new file mode 100644 index 0000000000..e3d7452eb1 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/springJdbc-config.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql new file mode 100644 index 0000000000..b9ef8fec25 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/test-data.sql @@ -0,0 +1,7 @@ +INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada'); + +INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA'); + +INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland'); + +INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA'); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml new file mode 100644 index 0000000000..ec0dc2469a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..716a96fde3 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +jdbc.pass= + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=true +hibernate.cache.use_query_cache=true +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties new file mode 100644 index 0000000000..b3cfd31f46 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true +jdbc.eventGeneratedId=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop + +# envers.X +envers.audit_table_suffix=_audit_log diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml new file mode 100644 index 0000000000..57687c306d --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml new file mode 100644 index 0000000000..5ea2d9c05b --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql new file mode 100644 index 0000000000..9cedb75c37 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql @@ -0,0 +1,20 @@ +DELIMITER // + CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255)) + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo WHERE name = fooName; + END // +DELIMITER ; + + +DELIMITER // + CREATE PROCEDURE GetAllFoos() + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo; + END // +DELIMITER ; \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java new file mode 100644 index 0000000000..c41423643a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java @@ -0,0 +1,185 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.test.annotation.Commit; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TestTransaction; +import org.springframework.transaction.annotation.Transactional; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { HibernateConf.class }) +@Transactional +public class HibernateBootstrapIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void whenBootstrapHibernateSession_thenNoException() { + + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + } + + @Test + public void whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertTrue(TestTransaction.isFlaggedForRollback()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertTrue(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + + @Test + @Commit + public void givenTransactionCommitDefault_whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertFalse(TestTransaction.isFlaggedForRollback()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.flagForRollback(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java new file mode 100644 index 0000000000..5b811ad576 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Assert; +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.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { HibernateXMLConf.class }) +@Transactional +public class HibernateXMLBootstrapIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void whenBootstrapHibernateSession_thenNoException() { + + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/jdbc/EmployeeDAOIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/jdbc/EmployeeDAOIntegrationTest.java similarity index 98% rename from spring-all/src/test/java/org/baeldung/jdbc/EmployeeDAOIntegrationTest.java rename to persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/jdbc/EmployeeDAOIntegrationTest.java index 4a92aa838f..453656098a 100644 --- a/spring-all/src/test/java/org/baeldung/jdbc/EmployeeDAOIntegrationTest.java +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/jdbc/EmployeeDAOIntegrationTest.java @@ -1,9 +1,9 @@ -package org.baeldung.jdbc; +package com.baeldung.jdbc; import java.util.ArrayList; import java.util.List; -import org.baeldung.jdbc.config.SpringJdbcConfig; +import com.baeldung.jdbc.config.SpringJdbcConfig; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java new file mode 100644 index 0000000000..fbda459d65 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java @@ -0,0 +1,157 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import com.baeldung.config.PersistenceJPAConfig; +import com.baeldung.persistence.model.Foo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooPaginationPersistenceIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private FooService fooService; + + @Before + public final void before() { + final int minimalNumberOfEntities = 25; + if (fooService.findAll().size() <= minimalNumberOfEntities) { + for (int i = 0; i < minimalNumberOfEntities; i++) { + fooService.create(new Foo(randomAlphabetic(6))); + } + } + } + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingFirstPage_thenCorrect() { + final int pageSize = 10; + + final Query query = entityManager.createQuery("From Foo"); + configurePagination(query, 1, pageSize); + + // When + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingLastPage_thenCorrect() { + final int pageSize = 10; + final Query queryTotal = entityManager.createQuery("Select count(f.id) from Foo f"); + final long countResult = (long) queryTotal.getSingleResult(); + + final Query query = entityManager.createQuery("Select f from Foo as f order by f.id"); + final int lastPage = (int) ((countResult / pageSize) + 1); + configurePagination(query, lastPage, pageSize); + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(lessThan(pageSize + 1))); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingPage_thenCorrect() { + final int pageSize = 10; + + final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.name"); + final List fooIds = queryIds.getResultList(); + + final Query query = entityManager.createQuery("Select f from Foo as f where f.id in :ids"); + query.setParameter("ids", fooIds.subList(0, pageSize)); + + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @Test + public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenCorrect() { + final int pageSize = 10; + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + final TypedQuery typedQuery = entityManager.createQuery(select); + typedQuery.setFirstResult(0); + typedQuery.setMaxResults(pageSize); + final List fooList = typedQuery.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @Test + public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenNoExceptions() { + int pageNumber = 1; + final int pageSize = 10; + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + final CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class); + countQuery.select(criteriaBuilder.count(countQuery.from(Foo.class))); + final Long count = entityManager.createQuery(countQuery).getSingleResult(); + + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + + TypedQuery typedQuery; + while (pageNumber < count.intValue()) { + typedQuery = entityManager.createQuery(select); + typedQuery.setFirstResult(pageNumber - 1); + typedQuery.setMaxResults(pageSize); + System.out.println("Current page: " + typedQuery.getResultList()); + pageNumber += pageSize; + } + + } + + // UTIL + + final int determineLastPage(final int pageSize, final long countResult) { + return (int) (countResult / pageSize) + 1; + } + + final void configurePagination(final Query query, final int pageNumber, final int pageSize) { + query.setFirstResult((pageNumber - 1) * pageSize); + query.setMaxResults(pageSize); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..f4b70a7fde --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java @@ -0,0 +1,69 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import com.baeldung.config.PersistenceJPAConfig; +import com.baeldung.persistence.model.Foo; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooServicePersistenceIntegrationTest { + + @Autowired + private FooService service; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Foo(randomAlphabetic(6))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenEntityWithLongNameIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + public final void whenSameEntityIsCreatedTwice_thenDataException() { + final Foo entity = new Foo(randomAlphabetic(8)); + service.create(entity); + service.create(entity); + } + + @Test(expected = DataAccessException.class) + public final void temp_whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test + public final void whenEntityIsCreated_thenFound() { + final Foo fooEntity = new Foo("abc"); + service.create(fooEntity); + final Foo found = service.findOne(fooEntity.getId()); + Assert.assertNotNull(found); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java new file mode 100644 index 0000000000..c3db45ab41 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingIntegrationTest.java @@ -0,0 +1,118 @@ +package com.baeldung.persistence.service; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import com.baeldung.config.PersistenceJPAConfig; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Foo; +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +@SuppressWarnings("unchecked") +public class FooServiceSortingIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + // tests + + @Test + public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.id"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() { + final String jql = "Select f from Foo as f order by f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByTwoAttributes_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.name asc, f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooByBar_thenBarsSorted() { + final String jql = "Select f from Foo as f order by f.name, f.bar.id"; + final Query barJoinQuery = entityManager.createQuery(jql); + final List fooList = barJoinQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + if (foo.getBar() != null) { + System.out.print("-------BarId:" + foo.getBar().getId()); + } + } + } + + @Test + public final void whenSortinfBar_thenPrintBarsSortedWithFoos() { + final String jql = "Select b from Bar as b order by b.id"; + final Query barQuery = entityManager.createQuery(jql); + final List barList = barQuery.getResultList(); + for (final Bar bar : barList) { + System.out.println("Bar Id:" + bar.getId()); + for (final Foo foo : bar.getFooList()) { + System.out.println("FooName:" + foo.getName()); + } + } + } + + @Test + public final void whenSortingFooWithCriteria_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java new file mode 100644 index 0000000000..103321fc64 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import com.baeldung.config.PersistenceJPAConfig; +import com.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +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; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooServiceSortingWitNullsManualIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private FooService service; + + // tests + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullLast_thenLastNull() { + service.create(new Foo()); + service.create(new Foo(randomAlphabetic(6))); + + final String jql = "Select f from Foo as f order by f.name desc NULLS LAST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullFirst_thenFirstNull() { + service.create(new Foo()); + + final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java new file mode 100644 index 0000000000..32a94ea3cb --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java @@ -0,0 +1,123 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import com.baeldung.config.PersistenceConfig; +import com.baeldung.persistence.model.Foo; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.exception.SQLGrammarException; +import org.hibernate.query.NativeQuery; +import org.hibernate.query.Query; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooStoredProceduresLiveTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresLiveTest.class); + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + private FooService fooService; + + private Session session; + + @Before + public final void before() { + session = sessionFactory.openSession(); + Assume.assumeTrue(getAllFoosExists()); + Assume.assumeTrue(getFoosByNameExists()); + } + + private boolean getFoosByNameExists() { + try { + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e); + return false; + } + } + + private boolean getAllFoosExists() { + try { + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e); + return false; + } + } + + @After + public final void after() { + session.close(); + } + + @Test + public final void getAllFoosUsingStoredProcedures() { + + fooService.create(new Foo(randomAlphabetic(6))); + + // Stored procedure getAllFoos using createSQLQuery + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + List allFoos = sqlQuery.list(); + for (Foo foo : allFoos) { + LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName()); + } + assertEquals(allFoos.size(), fooService.findAll().size()); + + // Stored procedure getAllFoos using a Named Query + @SuppressWarnings("unchecked") + Query namedQuery = session.getNamedQuery("callGetAllFoos"); + List allFoos2 = namedQuery.list(); + for (Foo foo : allFoos2) { + LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName()); + } + assertEquals(allFoos2.size(), fooService.findAll().size()); + } + + @Test + public final void getFoosByNameUsingStoredProcedures() { + + fooService.create(new Foo("NewFooName")); + + // Stored procedure getFoosByName using createSQLQuery() + @SuppressWarnings("unchecked") + Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)").addEntity(Foo.class).setParameter("fooName", "NewFooName"); + List allFoosByName = sqlQuery.list(); + for (Foo foo : allFoosByName) { + LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString()); + } + + // Stored procedure getFoosByName using getNamedQuery() + @SuppressWarnings("unchecked") + Query namedQuery = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName"); + List allFoosByName2 = namedQuery.list(); + for (Foo foo : allFoosByName2) { + LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString()); + } + + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java new file mode 100644 index 0000000000..d002ff7575 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java @@ -0,0 +1,561 @@ +package com.baeldung.spring.data.persistence.dao.user; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import javax.persistence.EntityManager; +import javax.persistence.Query; + +import com.baeldung.spring.data.persistence.config.PersistenceConfig; +import com.baeldung.spring.data.persistence.model.User; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.JpaSort; +import org.springframework.data.mapping.PropertyReferenceException; +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; +import org.springframework.transaction.annotation.Transactional; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class UserRepositoryCommon { + + final String USER_EMAIL = "email@example.com"; + final String USER_EMAIL2 = "email2@example.com"; + final String USER_EMAIL3 = "email3@example.com"; + final String USER_EMAIL4 = "email4@example.com"; + final Integer INACTIVE_STATUS = 0; + final Integer ACTIVE_STATUS = 1; + 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; + @Autowired + private EntityManager entityManager; + + @Test + @Transactional + public void givenUsersWithSameNameInDB_WhenFindAllByName_ThenReturnStreamOfUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + User user4 = new User(); + user4.setName("SAMPLE"); + user4.setEmail(USER_EMAIL4); + userRepository.save(user4); + + try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { + assertThat(foundUsersStream.count()).isEqualTo(3l); + } + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotation_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsers(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotationNative_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsersNative(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotation_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatus(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotationNative_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatusNative(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationIndexedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParams(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNativeNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParamsNative(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsCustomNames_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByUserStatusAndUserName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationIndexedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLike("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNamedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNamedParam("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNative_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNative("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithSortByName_ThenReturnUsersSorted() { + 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")); + + assertThat(usersSortByName.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test(expected = PropertyReferenceException.class) + public void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() { + 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")); + + List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllSortWithFunctionQueryAnnotationJPQL_ThenReturnUsersSorted() { + 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(Sort.by("name")); + + List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationJPQL_ThenReturnPageOfUsers() { + 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(PageRequest.of(1, 3)); + + assertThat(usersPage.getContent() + .get(0) + .getName()).isEqualTo("SAMPLE1"); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationNative_ThenReturnPageOfUsers() { + 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(PageRequest.of(1, 3)); + + assertThat(usersSortByNameLength.getContent() + .get(0) + .getName()).isEqualTo(USER_NAME_PETER); + } + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationJPQL_ThenModifyMatchingUsers() { + 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"); + + assertThat(updatedUsersSize).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindByEmailsWithDynamicQuery_ThenReturnCollection() { + + User user1 = new User(); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + Set emails = new HashSet<>(); + emails.add(USER_EMAIL2); + emails.add(USER_EMAIL3); + + Collection usersWithEmails = userRepository.findUserByEmails(emails); + + assertThat(usersWithEmails.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDBWhenFindByNameListReturnCollection() { + + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + List names = Arrays.asList(USER_NAME_ADAM, USER_NAME_PETER); + + List usersWithNames = userRepository.findUserByNameList(names); + + assertThat(usersWithNames.size()).isEqualTo(2); + } + + + @Test + @Transactional + public void whenInsertedWithQuery_ThenUserIsPersisted() { + userRepository.insertUser(USER_NAME_ADAM, 1, USER_EMAIL, ACTIVE_STATUS, true); + userRepository.insertUser(USER_NAME_PETER, 1, USER_EMAIL2, ACTIVE_STATUS, true); + + 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); + } + + + @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.com", 0); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + int deletedUsersCount = userRepository.deleteDeactivatedUsers(); + + List users = userRepository.findAll(); + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + assertEquals(1, deletedUsersCount); + } + + @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 where NAME = 'usr01'"); + assertEquals(0, nativeQuery.getResultList().get(0)); + } + + @After + public void cleanUp() { + userRepository.deleteAll(); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..2a9bffaeae --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java @@ -0,0 +1,38 @@ +package com.baeldung.spring.data.persistence.dao.user; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; + +import com.baeldung.spring.data.persistence.config.PersistenceConfig; +import com.baeldung.spring.data.persistence.model.User; +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; +import org.springframework.transaction.annotation.Transactional; + +/** + * Created by adam. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class UserRepositoryIntegrationTest extends UserRepositoryCommon { + + @Test + @Transactional + public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeThenModifyMatchingUsers() { + 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"); + + assertThat(updatedUsersSize).isEqualTo(2); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..2bccada9fe --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java @@ -0,0 +1,256 @@ +package com.baeldung.spring.data.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.util.IDUtil; +import org.hamcrest.Matchers; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.dao.DataAccessException; + +import com.baeldung.persistence.dao.common.IOperations; + +public abstract class AbstractServicePersistenceIntegrationTest { + + // tests + + // find - one + + @Test + /**/public final void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoResourceIsReceived() { + // When + final Foo createdResource = getApi().findOne(IDUtil.randomPositiveLong()); + + // Then + assertNull(createdResource); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenNoExceptions() { + final Foo existingResource = persistNewEntity(); + getApi().findOne(existingResource.getId()); + } + + @Test + public void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoExceptions() { + getApi().findOne(IDUtil.randomPositiveLong()); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenTheResultIsNotNull() { + final Foo existingResource = persistNewEntity(); + final Foo retrievedResource = getApi().findOne(existingResource.getId()); + assertNotNull(retrievedResource); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenResourceIsRetrievedCorrectly() { + final Foo existingResource = persistNewEntity(); + final Foo retrievedResource = getApi().findOne(existingResource.getId()); + assertEquals(existingResource, retrievedResource); + } + + // find - one - by name + + // find - all + + @Test + /**/public void whenAllResourcesAreRetrieved_thenNoExceptions() { + getApi().findAll(); + } + + @Test + /**/public void whenAllResourcesAreRetrieved_thenTheResultIsNotNull() { + final List resources = getApi().findAll(); + + assertNotNull(resources); + } + + @Test + /**/public void givenAtLeastOneResourceExists_whenAllResourcesAreRetrieved_thenRetrievedResourcesAreNotEmpty() { + persistNewEntity(); + + // When + final List allResources = getApi().findAll(); + + // Then + assertThat(allResources, not(Matchers. empty())); + } + + @Test + /**/public void givenAnResourceExists_whenAllResourcesAreRetrieved_thenTheExistingResourceIsIndeedAmongThem() { + final Foo existingResource = persistNewEntity(); + + final List resources = getApi().findAll(); + + assertThat(resources, hasItem(existingResource)); + } + + @Test + /**/public void whenAllResourcesAreRetrieved_thenResourcesHaveIds() { + persistNewEntity(); + + // When + final List allResources = getApi().findAll(); + + // Then + for (final Foo resource : allResources) { + assertNotNull(resource.getId()); + } + } + + // create + + @Test(expected = RuntimeException.class) + /**/public void whenNullResourceIsCreated_thenException() { + getApi().create(null); + } + + @Test + /**/public void whenResourceIsCreated_thenNoExceptions() { + persistNewEntity(); + } + + @Test + /**/public void whenResourceIsCreated_thenResourceIsRetrievable() { + final Foo existingResource = persistNewEntity(); + + assertNotNull(getApi().findOne(existingResource.getId())); + } + + @Test + /**/public void whenResourceIsCreated_thenSavedResourceIsEqualToOriginalResource() { + final Foo originalResource = createNewEntity(); + final Foo savedResource = getApi().create(originalResource); + + assertEquals(originalResource, savedResource); + } + + @Test(expected = RuntimeException.class) + public void whenResourceWithFailedConstraintsIsCreated_thenException() { + final Foo invalidResource = createNewEntity(); + invalidate(invalidResource); + + getApi().create(invalidResource); + } + + /** + * -- specific to the persistence engine + */ + @Test(expected = DataAccessException.class) + @Ignore("Hibernate simply ignores the id silently and still saved (tracking this)") + public void whenResourceWithIdIsCreated_thenDataAccessException() { + final Foo resourceWithId = createNewEntity(); + resourceWithId.setId(IDUtil.randomPositiveLong()); + + getApi().create(resourceWithId); + } + + // update + + @Test(expected = RuntimeException.class) + /**/public void whenNullResourceIsUpdated_thenException() { + getApi().update(null); + } + + @Test + /**/public void givenResourceExists_whenResourceIsUpdated_thenNoExceptions() { + // Given + final Foo existingResource = persistNewEntity(); + + // When + getApi().update(existingResource); + } + + /** + * - can also be the ConstraintViolationException which now occurs on the update operation will not be translated; as a consequence, it will be a TransactionSystemException + */ + @Test(expected = RuntimeException.class) + public void whenResourceIsUpdatedWithFailedConstraints_thenException() { + final Foo existingResource = persistNewEntity(); + invalidate(existingResource); + + getApi().update(existingResource); + } + + @Test + /**/public void givenResourceExists_whenResourceIsUpdated_thenUpdatesArePersisted() { + // Given + final Foo existingResource = persistNewEntity(); + + // When + change(existingResource); + getApi().update(existingResource); + + final Foo updatedResource = getApi().findOne(existingResource.getId()); + + // Then + assertEquals(existingResource, updatedResource); + } + + // delete + + // @Test(expected = RuntimeException.class) + // public void givenResourceDoesNotExists_whenResourceIsDeleted_thenException() { + // // When + // getApi().delete(IDUtil.randomPositiveLong()); + // } + // + // @Test(expected = RuntimeException.class) + // public void whenResourceIsDeletedByNegativeId_thenException() { + // // When + // getApi().delete(IDUtil.randomNegativeLong()); + // } + // + // @Test + // public void givenResourceExists_whenResourceIsDeleted_thenNoExceptions() { + // // Given + // final Foo existingResource = persistNewEntity(); + // + // // When + // getApi().delete(existingResource.getId()); + // } + // + // @Test + // /**/public final void givenResourceExists_whenResourceIsDeleted_thenResourceNoLongerExists() { + // // Given + // final Foo existingResource = persistNewEntity(); + // + // // When + // getApi().delete(existingResource.getId()); + // + // // Then + // assertNull(getApi().findOne(existingResource.getId())); + // } + + // template method + + protected Foo createNewEntity() { + return new Foo(randomAlphabetic(6)); + } + + protected abstract IOperations getApi(); + + private final void invalidate(final Foo entity) { + entity.setName(null); + } + + private final void change(final Foo entity) { + entity.setName(randomAlphabetic(6)); + } + + protected Foo persistNewEntity() { + return getApi().create(createNewEntity()); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..8f628c5615 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.spring.data.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertNotNull; + +import com.baeldung.spring.data.persistence.model.Foo; +import com.baeldung.spring.data.persistence.config.PersistenceConfig; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.dao.common.IOperations; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooServicePersistenceIntegrationTest extends AbstractServicePersistenceIntegrationTest { + + @Autowired + private IFooService service; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Foo(randomAlphabetic(6))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo()); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenEntityWithLongNameIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + // custom Query method + + @Test + public final void givenUsingCustomQuery_whenRetrievingEntity_thenFound() { + final String name = randomAlphabetic(6); + service.create(new Foo(name)); + + final Foo retrievedByName = service.retrieveByName(name); + assertNotNull(retrievedByName); + } + + // work in progress + + @Test(expected = InvalidDataAccessApiUsageException.class) + @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail") + public final void whenSameEntityIsCreatedTwice_thenDataException() { + final Foo entity = new Foo(randomAlphabetic(8)); + service.create(entity); + service.create(entity); + } + + // API + + @Override + protected final IOperations getApi() { + return service; + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/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 5aa438132e..b4fed5150d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,12 +7,13 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - - lombok-custom - parent-modules pom + + quarkus + + @@ -122,22 +123,22 @@ - - org.junit.platform - junit-platform-surefire-provider - ${junit-platform.version} - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - - + + org.junit.platform + junit-platform-surefire-provider + ${junit-platform.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + + org.apache.maven.plugins @@ -232,6 +233,7 @@ ${maven-war-plugin.version} + com.vackosar.gitflowincrementalbuilder @@ -331,11 +333,12 @@ parent-spring-5 parent-java parent-kotlin - + akka-streams algorithms-genetic algorithms-miscellaneous-1 algorithms-miscellaneous-2 + algorithms-miscellaneous-3 algorithms-sorting animal-sniffer-mvn-plugin annotations @@ -366,28 +369,50 @@ axon azure + blade + bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy - - - core-java-8 - - core-java-arrays - core-java-collections - core-java-concurrency-collections - core-java-io - core-java-lang - core-java-networking - core-java-sun + core-groovy-2 + core-groovy-collections + + + + core-java-modules/core-java-8 + core-java-modules/core-java-8-2 + core-java-modules/core-java-lambdas + + + core-java-modules/core-java-arrays + core-java-modules/core-java-collections + core-java-modules/core-java-collections-list + core-java-modules/core-java-collections-list-2 + core-java-modules/core-java-collections-array-list + core-java-modules/core-java-collections-set + core-java-modules/core-java-concurrency-basic + core-java-modules/core-java-concurrency-collections + core-java-modules/core-java-io + core-java-modules/core-java-nio + core-java-modules/core-java-security + core-java-modules/core-java-lang-syntax + core-java-modules/core-java-lang + core-java-modules/core-java-lang-oop + core-java-modules/core-java-lang-oop-2 + core-java-modules + core-java-modules/core-java-networking + core-java-modules/core-java-perf + core-java-modules/core-java-reflection + core-java-modules/core-java-sun + core-java-modules/core-java + core-java-modules/core-java-jvm core-scala couchbase custom-pmd - + dagger data-structures ddd @@ -395,14 +420,15 @@ disruptor dozer drools - dubbo - + dubbo + + easy-random ethereum - + feign flyway-cdi-extension - - + + geotools google-cloud google-web-toolkit @@ -412,31 +438,36 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice - + hazelcast helidon httpclient + httpclient-simple hystrix - + image-processing immutables jackson + jackson-2 + jackson-simple java-collections-conversions java-collections-maps + java-collections-maps-2 - java-ee-8-security-api + + java-lite java-numbers java-rmi java-spi java-streams + java-strings + java-strings-2 java-vavr-stream java-websocket javafx @@ -449,6 +480,8 @@ jersey JGit jgroups + jhipster + jhipster-5 jib jjwt jmeter @@ -463,17 +496,19 @@ kotlin-libraries - + kotlin-libraries-2 + + libraries + libraries-2 libraries-data libraries-apache-commons + libraries-primitive libraries-security libraries-server + libraries-http linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene @@ -491,9 +526,8 @@ mustache mybatis - - noexception - + + optaplanner orika osgi @@ -503,66 +537,32 @@ performance-tests 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-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 + quarkus + rabbitmq ratpack reactor-core rest-with-spark-java resteasy - + restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava - rxjava-2 - + rxjava-2 + software-security/sql-injection-samples + + tensorflow-java + spring-boot-flowable + spring-security-kerberos + - + default-second @@ -596,13 +596,15 @@ parent-spring-5 parent-java parent-kotlin - + saas spark-java - + spring-4 - + spring-5 + spring-5-webflux + spring-5-data-reactive spring-5-mvc spring-5-reactive spring-5-reactive-client @@ -610,24 +612,28 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth - + spring-5-security-cognito + spring-activiti spring-akka spring-all spring-amqp + spring-amqp-simple spring-aop spring-apache-camel spring-batch spring-bom - + spring-boot spring-boot-admin + spring-boot-angular spring-boot-angular-ecommerce spring-boot-autoconfiguration spring-boot-bootstrap spring-boot-camel spring-boot-client + spring-boot-crud spring-boot-ctx-fluent spring-boot-custom-starter @@ -637,44 +643,53 @@ spring-boot-keycloak spring-boot-logging-log4j2 spring-boot-mvc + spring-boot-mvc-birt spring-boot-ops + spring-boot-ops-2 + spring-boot-rest + spring-boot-data + spring-boot-parent spring-boot-property-exp spring-boot-security + spring-boot-testing spring-boot-vue - + spring-boot-libraries + spring-cloud spring-cloud-bus spring-cloud-data-flow - + spring-core + spring-core-2 spring-cucumber - + spring-data-rest spring-data-rest-querydsl spring-dispatcher-servlet spring-drools - + + spring-ehcache spring-ejb spring-exceptions - + spring-freemarker - + spring-groovy - + spring-integration - + spring-jenkins-pipeline spring-jersey spring-jinq spring-jms spring-jooq - + spring-kafka spring-katharsis - + spring-ldap - + spring-mobile spring-mockito spring-mvc-forms-jsp @@ -682,14 +697,16 @@ spring-mvc-java spring-mvc-kotlin spring-mvc-simple + spring-mvc-simple-2 spring-mvc-velocity spring-mvc-webflow spring-mvc-xml - + spring-protobuf - + + spring-quartz - + spring-reactive-kotlin spring-reactor spring-remoting @@ -702,23 +719,17 @@ spring-rest-simple spring-resttemplate spring-roo - spring-security-acl 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 spring-security-mvc-custom spring-security-mvc-digest-auth + spring-security-mvc-jsonview spring-security-mvc-ldap spring-security-mvc-login spring-security-mvc-persisted-remember-me @@ -735,68 +746,56 @@ spring-security-x509 spring-session spring-sleuth + spring-soap spring-social-login spring-spel spring-state-machine spring-static-resources spring-swagger-codegen - + spring-thymeleaf - + spring-userservice - + spring-vault spring-vertx - + spring-webflux-amqp - + spring-zuul - + static-analysis stripe 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 - + undertow - + vavr vertx vertx-and-rxjava video-tutorials vraptor - + wicket - + xml xmlunit-2 xstream - + + tensorflow-java + spring-boot-flowable + spring-security-kerberos + - + spring-context @@ -826,6 +825,7 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth + spring-5-security-cognito spring-activiti spring-akka spring-all @@ -833,35 +833,30 @@ 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 spring-boot-client spring-boot-custom-starter - greeter-spring-boot-autoconfigure + greeter-spring-boot-autoconfigure greeter-spring-boot-sample-app persistence-modules/spring-boot-h2/spring-boot-h2-database 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 @@ -874,6 +869,7 @@ spring-data-rest spring-dispatcher-servlet spring-drools + spring-ehcache spring-freemarker persistence-modules/spring-hibernate-3 persistence-modules/spring-hibernate4 @@ -908,13 +904,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 @@ -924,14 +914,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 @@ -943,10 +930,14 @@ spring-vault spring-vertx spring-zuul/spring-zuul-foos-resource + persistence-modules/hibernate-mapping persistence-modules/spring-data-dynamodb persistence-modules/spring-data-eclipselink persistence-modules/spring-data-solr persistence-modules/spring-hibernate-5 + + spring-boot-flowable + spring-security-kerberos @@ -984,29 +975,27 @@ parent-spring-5 parent-java parent-kotlin - - core-java - core-java-concurrency + + core-java-modules/core-java-concurrency-advanced core-kotlin + core-kotlin-2 + core-kotlin-io jenkins/hello-world - jhipster jws libraries persistence-modules/hibernate5 + persistence-modules/hibernate-mapping persistence-modules/java-jpa persistence-modules/java-mongodb - persistence-modules/jnosql + persistence-modules/jnosql - spring-5-data-reactive - spring-amqp-simple - - vaadin + vaadin - + integration-lite-first @@ -1036,11 +1025,12 @@ parent-spring-5 parent-java parent-kotlin - + akka-streams algorithms-genetic algorithms-miscellaneous-1 algorithms-miscellaneous-2 + algorithms-miscellaneous-3 algorithms-sorting animal-sniffer-mvn-plugin annotations @@ -1073,26 +1063,41 @@ bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy - - - core-java-8 - - core-java-arrays - core-java-collections - core-java-concurrency-collections - core-java-io - core-java-lang - core-java-networking - core-java-sun + core-groovy-2 + core-groovy-collections + + + core-java-modules/core-java-8 + core-java-modules/core-java-8-2 + + + core-java-modules/core-java-arrays + core-java-modules/core-java-collections + core-java-modules/core-java-collections-list + core-java-modules/core-java-collections-list-2 + core-java-modules/core-java-collections-array-list + core-java-modules/core-java-collections-set + core-java-modules/core-java-concurrency-basic + core-java-modules/core-java-concurrency-collections + core-java-modules/core-java-io + core-java-modules/core-java-nio + core-java-modules/core-java-security + core-java-modules/core-java-lang-syntax + core-java-modules/core-java-lang + core-java-modules/core-java-lang-oop + core-java-modules/core-java-lang-oop-2 + core-java-modules + core-java-modules/core-java-networking + core-java-modules/core-java-perf + core-java-modules/core-java-sun core-scala couchbase custom-pmd - + dagger data-structures ddd @@ -1100,14 +1105,14 @@ disruptor dozer drools - dubbo - + dubbo + ethereum - + feign flyway-cdi-extension - - + + geotools google-cloud google-web-toolkit @@ -1117,23 +1122,25 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice - + hazelcast helidon httpclient + httpclient-simple hystrix - + image-processing immutables jackson + jackson-2 + jackson-simple java-collections-conversions java-collections-maps + java-collections-maps-2 java-ee-8-security-api java-lite @@ -1141,7 +1148,9 @@ java-rmi java-spi java-streams + java-strings + java-strings-2 java-vavr-stream java-websocket javafx @@ -1154,6 +1163,8 @@ jersey JGit jgroups + jhipster + jhipster-5 jib jjwt jmeter @@ -1168,22 +1179,22 @@ kotlin-libraries - + + libraries libraries-data libraries-apache-commons libraries-security libraries-server + libraries-http linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene mapstruct maven + maven-archetype maven-polyglot/maven-polyglot-json-extension @@ -1196,9 +1207,8 @@ mustache mybatis - - noexception - + + optaplanner orika osgi @@ -1208,62 +1218,22 @@ performance-tests 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-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 reactor-core rest-with-spark-java resteasy - + restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava - rxjava-2 - + rxjava-2 + @@ -1297,13 +1267,14 @@ parent-spring-5 parent-java parent-kotlin - + saas spark-java - + spring-4 - + spring-5 + spring-5-data-reactive spring-5-mvc spring-5-reactive spring-5-reactive-client @@ -1311,18 +1282,20 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth - + spring-5-security-cognito spring-activiti spring-akka spring-all spring-amqp + spring-amqp-simple spring-aop spring-apache-camel spring-batch spring-bom - + spring-boot spring-boot-admin + spring-boot-angular spring-boot-angular-ecommerce spring-boot-autoconfiguration spring-boot-bootstrap @@ -1338,44 +1311,51 @@ spring-boot-keycloak spring-boot-logging-log4j2 spring-boot-mvc + spring-boot-mvc-birt spring-boot-ops + spring-boot-ops-2 + spring-boot-rest + spring-boot-data + spring-boot-parent spring-boot-property-exp spring-boot-security spring-boot-vue - + spring-cloud spring-cloud-bus spring-cloud-data-flow - + spring-core + spring-core-2 spring-cucumber - + spring-data-rest spring-data-rest-querydsl spring-dispatcher-servlet spring-drools - + + spring-ehcache spring-ejb spring-exceptions - + spring-freemarker - + spring-groovy - + spring-integration - + spring-jenkins-pipeline spring-jersey spring-jinq spring-jms spring-jooq - + spring-kafka spring-katharsis - + spring-ldap - + spring-mobile spring-mockito spring-mvc-forms-jsp @@ -1383,14 +1363,16 @@ spring-mvc-java spring-mvc-kotlin spring-mvc-simple + spring-mvc-simple-2 spring-mvc-velocity spring-mvc-webflow spring-mvc-xml - + spring-protobuf - + + spring-quartz - + spring-reactive-kotlin spring-reactor spring-remoting @@ -1403,19 +1385,13 @@ spring-rest-simple spring-resttemplate spring-roo - + spring-security-acl 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 spring-security-mvc-custom @@ -1436,64 +1412,48 @@ spring-security-x509 spring-session spring-sleuth + spring-soap spring-social-login spring-spel spring-state-machine spring-static-resources spring-swagger-codegen - + spring-thymeleaf - + spring-userservice - + spring-vault spring-vertx - + spring-webflux-amqp - + spring-zuul - + static-analysis stripe 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 - + undertow - + vavr vertx vertx-and-rxjava video-tutorials vraptor - + wicket - + xml xmlunit-2 xstream - + @@ -1527,13 +1487,13 @@ parent-spring-5 parent-java parent-kotlin - - core-java - core-java-concurrency + + core-java-modules/core-java + core-java-modules/core-java-concurrency-advanced core-kotlin + core-kotlin-2 jenkins/hello-world - jhipster jws libraries @@ -1541,12 +1501,9 @@ persistence-modules/hibernate5 persistence-modules/java-jpa persistence-modules/java-mongodb - persistence-modules/jnosql + persistence-modules/jnosql - spring-5-data-reactive - spring-amqp-simple - - vaadin + vaadin @@ -1567,21 +1524,23 @@ UTF-8 UTF-8 - refs/heads/master - true + refs/remotes/origin/master + true + false false false false - + 4.12 1.3 2.21.0 - + 1.7.21 1.1.7 - + + 2.21.0 3.7.0 1.6.0 @@ -1593,8 +1552,9 @@ 1.19 1.3 1.6.0 - 2.19.1 + 2.21.0 2.5 + 2.6 1.4 3.0.0 3.1.0 @@ -1602,16 +1562,18 @@ 2.3.1 1.9.13 1.2 - 2.5.0 + 2.9.8 1.3 1.2.0 5.2.0 0.3.1 2.5.1 0.0.1 - 3.4 + 3.8 2.3 3.8 + 1.16.12 + 1.4.197 diff --git a/quarkus/.dockerignore b/quarkus/.dockerignore new file mode 100644 index 0000000000..b86c7ac340 --- /dev/null +++ b/quarkus/.dockerignore @@ -0,0 +1,4 @@ +* +!target/*-runner +!target/*-runner.jar +!target/lib/* \ No newline at end of file diff --git a/quarkus/.mvn/wrapper/MavenWrapperDownloader.java b/quarkus/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100755 index 0000000000..b20a55a7a9 --- /dev/null +++ b/quarkus/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or 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. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.3"; + /** + * 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/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + " .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 directory '" + 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 { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + 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/quarkus/.mvn/wrapper/maven-wrapper.jar b/quarkus/.mvn/wrapper/maven-wrapper.jar new file mode 100755 index 0000000000..e89f07c229 Binary files /dev/null and b/quarkus/.mvn/wrapper/maven-wrapper.jar differ diff --git a/quarkus/.mvn/wrapper/maven-wrapper.properties b/quarkus/.mvn/wrapper/maven-wrapper.properties new file mode 100755 index 0000000000..1703626ce7 --- /dev/null +++ b/quarkus/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar diff --git a/quarkus/README.md b/quarkus/README.md new file mode 100644 index 0000000000..01009eab3e --- /dev/null +++ b/quarkus/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Guide to QuarkusIO](hhttps://www.baeldung.com/quarkus-io) diff --git a/quarkus/mvnw b/quarkus/mvnw new file mode 100755 index 0000000000..34d9dae8d0 --- /dev/null +++ b/quarkus/mvnw @@ -0,0 +1,305 @@ +#!/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)`" +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 + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar" + fi + 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 $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + 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/quarkus/mvnw.cmd b/quarkus/mvnw.cmd new file mode 100755 index 0000000000..77b451d837 --- /dev/null +++ b/quarkus/mvnw.cmd @@ -0,0 +1,172 @@ +@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.5.3/maven-wrapper-0.5.3.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 ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar" + ) + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $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/quarkus/pom.xml b/quarkus/pom.xml new file mode 100644 index 0000000000..d8f274df6d --- /dev/null +++ b/quarkus/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + com.baeldung.quarkus + quarkus + 1.0-SNAPSHOT + + 2.22.0 + 0.13.1 + 1.8 + UTF-8 + 1.8 + + + + + io.quarkus + quarkus-bom + ${quarkus.version} + pom + import + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.version} + + + + build + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + + + + + + + + native + + + native + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.version} + + + + native-image + + + true + + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + + + + + + + + + + diff --git a/quarkus/src/main/docker/Dockerfile.jvm b/quarkus/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000000..c91417af87 --- /dev/null +++ b/quarkus/src/main/docker/Dockerfile.jvm @@ -0,0 +1,21 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the docker image run: +# +# mvn package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/quarkus-project-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-project-jvm +# +### +FROM fabric8/java-jboss-openjdk8-jdk +ENV JAVA_OPTIONS=-Dquarkus.http.host=0.0.0.0 +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/app.jar +ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/quarkus/src/main/docker/Dockerfile.native b/quarkus/src/main/docker/Dockerfile.native new file mode 100644 index 0000000000..f076fe3f60 --- /dev/null +++ b/quarkus/src/main/docker/Dockerfile.native @@ -0,0 +1,22 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +# +# Before building the docker image run: +# +# mvn package -Pnative -Dnative-image.docker-build=true +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-project . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/quarkus-project +# +### +FROM registry.fedoraproject.org/fedora-minimal +WORKDIR /work/ +COPY target/*-runner /work/application +RUN chmod 775 /work +EXPOSE 8080 +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] \ No newline at end of file diff --git a/quarkus/src/main/java/com/baeldung/quarkus/HelloResource.java b/quarkus/src/main/java/com/baeldung/quarkus/HelloResource.java new file mode 100644 index 0000000000..884275f313 --- /dev/null +++ b/quarkus/src/main/java/com/baeldung/quarkus/HelloResource.java @@ -0,0 +1,28 @@ +package com.baeldung.quarkus; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @Inject + HelloService helloService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/polite/{name}") + public String greeting(@PathParam("name") String name) { + return helloService.politeHello(name); + } + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} \ No newline at end of file diff --git a/quarkus/src/main/java/com/baeldung/quarkus/HelloService.java b/quarkus/src/main/java/com/baeldung/quarkus/HelloService.java new file mode 100644 index 0000000000..4b19de1b63 --- /dev/null +++ b/quarkus/src/main/java/com/baeldung/quarkus/HelloService.java @@ -0,0 +1,16 @@ +package com.baeldung.quarkus; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import javax.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HelloService { + + @ConfigProperty(name = "greeting") + private String greeting; + + public String politeHello(String name){ + return greeting + " " + name; + } +} diff --git a/quarkus/src/main/resources/META-INF/resources/index.html b/quarkus/src/main/resources/META-INF/resources/index.html new file mode 100644 index 0000000000..070a1f672b --- /dev/null +++ b/quarkus/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,152 @@ + + + + + quarkus-project - 1.0-SNAPSHOT + + + + +

+ +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html.

+ +

What can I do from here?

+ +

If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+
    +
  • Add REST resources, Servlets, functions and other services in src/main/java.
  • +
  • Your static assets are located in src/main/resources/META-INF/resources.
  • +
  • Configure your application in src/main/resources/application.properties. +
  • +
+ +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: com.baeldung.quarkus
  • +
  • ArtifactId: quarkus-project
  • +
  • Version: 1.0-SNAPSHOT
  • +
  • Quarkus Version: 0.13.1
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/quarkus/src/main/resources/application.properties b/quarkus/src/main/resources/application.properties new file mode 100644 index 0000000000..3f05d2198f --- /dev/null +++ b/quarkus/src/main/resources/application.properties @@ -0,0 +1,3 @@ +# Configuration file +# key = value +greeting=Good morning \ No newline at end of file diff --git a/quarkus/src/test/java/com/baeldung/quarkus/HelloResourceTest.java b/quarkus/src/test/java/com/baeldung/quarkus/HelloResourceTest.java new file mode 100644 index 0000000000..3d0fff7562 --- /dev/null +++ b/quarkus/src/test/java/com/baeldung/quarkus/HelloResourceTest.java @@ -0,0 +1,21 @@ +package com.baeldung.quarkus; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +@QuarkusTest +public class HelloResourceTest { + + @Test + public void testHelloEndpoint() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("hello")); + } + +} \ No newline at end of file diff --git a/quarkus/src/test/java/com/baeldung/quarkus/NativeHelloResourceIT.java b/quarkus/src/test/java/com/baeldung/quarkus/NativeHelloResourceIT.java new file mode 100644 index 0000000000..4b0606f588 --- /dev/null +++ b/quarkus/src/test/java/com/baeldung/quarkus/NativeHelloResourceIT.java @@ -0,0 +1,9 @@ +package com.baeldung.quarkus; + +import io.quarkus.test.junit.SubstrateTest; + +@SubstrateTest +public class NativeHelloResourceIT extends HelloResourceTest { + + // Execute the same tests but in native mode. +} \ No newline at end of file diff --git a/ratpack/README.md b/ratpack/README.md index dded42fab6..78e2f8ccfc 100644 --- a/ratpack/README.md +++ b/ratpack/README.md @@ -5,3 +5,5 @@ - [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) +- [Ratpack with Groovy](https://www.baeldung.com/ratpack-groovy) diff --git a/ratpack/build.gradle b/ratpack/build.gradle index 25af3ddb51..c997b4e697 100644 --- a/ratpack/build.gradle +++ b/ratpack/build.gradle @@ -14,6 +14,8 @@ if (!JavaVersion.current().java8Compatible) { apply plugin: "io.ratpack.ratpack-java" apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'io.ratpack.ratpack-groovy' repositories { jcenter() diff --git a/ratpack/pom.xml b/ratpack/pom.xml index 7de11e6955..0df313c05e 100644 --- a/ratpack/pom.xml +++ b/ratpack/pom.xml @@ -3,9 +3,9 @@ 4.0.0 com.baeldung ratpack - jar 1.0-SNAPSHOT ratpack + jar http://maven.apache.org @@ -26,11 +26,21 @@ ratpack-core ${ratpack.version} + + org.codehaus.groovy + groovy-sql + ${groovy.sql.version} + io.ratpack ratpack-hikari ${ratpack.version} + + io.ratpack + ratpack-groovy-test + ${ratpack.test.latest.version} + io.ratpack ratpack-hystrix @@ -61,7 +71,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.apache.httpcomponents @@ -90,8 +100,8 @@ 1.5.4 4.5.3 4.4.6 - 1.4.193 1.5.12 + 2.4.15 + 1.6.1 - diff --git a/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy b/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy new file mode 100644 index 0000000000..4d8814b627 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy @@ -0,0 +1,76 @@ +package com.baeldung; + +@Grab('io.ratpack:ratpack-groovy:1.6.1') +import static ratpack.groovy.Groovy.ratpack + +import com.baeldung.model.User +import com.google.common.reflect.TypeToken +import ratpack.exec.Promise +import ratpack.handling.Context +import ratpack.jackson.Jackson +import groovy.sql.Sql +import java.sql.Connection +import java.sql.PreparedStatement +import java.sql.ResultSet +import ratpack.hikari.HikariModule +import javax.sql.DataSource; + +ratpack { + serverConfig { port(5050) } + bindings { + module(HikariModule) { config -> + config.dataSourceClassName = 'org.h2.jdbcx.JdbcDataSource' + config.addDataSourceProperty('URL', "jdbc:h2:mem:devDB;INIT=RUNSCRIPT FROM 'classpath:/User.sql'") + } + } + + handlers { + + get { render 'Hello World from Ratpack with Groovy!!' } + + get("greet/:name") { Context ctx -> + render "Hello " + ctx.getPathTokens().get("name") + "!!!" + } + + get("data") { + render Jackson.json([title: "Mr", name: "Norman", country: "USA"]) + } + + post("user") { + Promise user = parse(Jackson.fromJson(User)) + user.then { u -> render u.name } + } + + get('fetchUserName/:id') { Context ctx -> + Connection connection = ctx.get(DataSource.class).getConnection() + PreparedStatement queryStatement = connection.prepareStatement("SELECT NAME FROM USER WHERE ID=?") + queryStatement.setInt(1, Integer.parseInt(ctx.getPathTokens().get("id"))) + ResultSet resultSet = queryStatement.executeQuery() + resultSet.next() + render resultSet.getString(1) + } + + get('fetchUsers') { + def db = [url:'jdbc:h2:mem:devDB'] + def sql = Sql.newInstance(db.url, db.user, db.password) + def users = sql.rows("SELECT * FROM USER"); + render(Jackson.json(users)) + } + + post('addUser') { + parse(Jackson.fromJson(User)) + .then { u -> + def db = [url:'jdbc:h2:mem:devDB'] + Sql sql = Sql.newInstance(db.url, db.user, db.password) + sql.executeInsert("INSERT INTO USER VALUES (?,?,?,?)", [ + u.id, + u.title, + u.name, + u.country + ]) + render "User $u.name inserted" + } + } + } +} + diff --git a/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy b/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy new file mode 100644 index 0000000000..95ada25e60 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy @@ -0,0 +1,12 @@ +package com.baeldung; + +public class RatpackGroovyApp { + + public static void main(String[] args) { + File file = new File("src/main/groovy/com/baeldung/Ratpack.groovy"); + def shell = new GroovyShell() + shell.evaluate(file) + } + +} + diff --git a/ratpack/src/main/groovy/com/baeldung/model/User.groovy b/ratpack/src/main/groovy/com/baeldung/model/User.groovy new file mode 100644 index 0000000000..0fe4c6c367 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/model/User.groovy @@ -0,0 +1,9 @@ +package com.baeldung.model + +class User { + + long id + String title + String name + String country +} 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); + } + +} diff --git a/ratpack/src/main/resources/User.sql b/ratpack/src/main/resources/User.sql new file mode 100644 index 0000000000..a3e2242283 --- /dev/null +++ b/ratpack/src/main/resources/User.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS USER; +CREATE TABLE USER ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + TITLE VARCHAR(255), + NAME VARCHAR(255), + COUNTRY VARCHAR(255) +); + +INSERT INTO USER VALUES(1,'Mr','Norman Potter', 'USA'); +INSERT INTO USER VALUES(2,'Miss','Ketty Smith', 'FRANCE'); \ No newline at end of file diff --git a/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy b/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy new file mode 100644 index 0000000000..726d703a06 --- /dev/null +++ b/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy @@ -0,0 +1,46 @@ +package com.baeldung; + +import ratpack.groovy.Groovy +import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest; +import ratpack.test.http.TestHttpClient; +import ratpack.test.ServerBackedApplicationUnderTest; +import org.junit.Test; +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import ratpack.test.MainClassApplicationUnderTest + +class RatpackGroovySpec { + + ServerBackedApplicationUnderTest ratpackGroovyApp = new MainClassApplicationUnderTest(RatpackGroovyApp.class) + @Delegate TestHttpClient client = TestHttpClient.testHttpClient(ratpackGroovyApp) + + @Test + void "test if app is started"() { + when: + get("") + + then: + assert response.statusCode == 200 + assert response.body.text == "Hello World from Ratpack with Groovy!!" + } + + @Test + void "test greet with name"() { + when: + get("greet/Lewis") + + then: + assert response.statusCode == 200 + assert response.body.text == "Hello Lewis!!!" + } + + @Test + void "test fetchUsers"() { + when: + get("fetchUsers") + + then: + assert response.statusCode == 200 + assert response.body.text == '[{"ID":1,"TITLE":"Mr","NAME":"Norman Potter","COUNTRY":"USA"},{"ID":2,"TITLE":"Miss","NAME":"Ketty Smith","COUNTRY":"FRANCE"}]' + } +} 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) 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(); + } +} diff --git a/rest-with-spark-java/pom.xml b/rest-with-spark-java/pom.xml index a0005b7dec..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.8.6 - 2.8.6 diff --git a/resteasy/bin/README.md b/resteasy/bin/README.md index 722f1dfe93..f4dba1493a 100644 --- a/resteasy/bin/README.md +++ b/resteasy/bin/README.md @@ -4,5 +4,3 @@ ### Relevant Articles: -- [A Guide to RESTEasy](http://www.baeldung.com/resteasy-tutorial) -- [RESTEasy Client API](http://www.baeldung.com/resteasy-client-tutorial) diff --git a/resteasy/bin/pom.xml b/resteasy/bin/pom.xml index f8cdc20360..15d8b5bd18 100644 --- a/resteasy/bin/pom.xml +++ b/resteasy/bin/pom.xml @@ -2,18 +2,11 @@ 4.0.0 - com.baeldung resteasy-tutorial 1.0 war - - 3.0.19.Final - 2.5 - 1.6.1 - - com.baeldung resteasy-tutorial @@ -80,4 +73,10 @@ ${commons-io.version} + + + 3.0.19.Final + 2.5 + 1.6.1 + \ No newline at end of file diff --git a/resteasy/pom.xml b/resteasy/pom.xml index 31a6ed485a..ca4124abca 100644 --- a/resteasy/pom.xml +++ b/resteasy/pom.xml @@ -5,8 +5,8 @@ com.baeldung resteasy 1.0 - war resteasy + war com.baeldung diff --git a/restx/pom.xml b/restx/pom.xml index c6233b968c..10c843a208 100644 --- a/restx/pom.xml +++ b/restx/pom.xml @@ -3,17 +3,10 @@ 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 - restx 0.1-SNAPSHOT + restx war - restx-demo - - - 1.8 - 1.8 - 0.35-rc4 - com.baeldung @@ -106,7 +99,7 @@ ch.qos.logback logback-classic - 1.0.13 + ${logback-classic.version} io.restx @@ -117,10 +110,11 @@ junit junit - 4.11 + ${junit.version} test + @@ -152,4 +146,11 @@ + + + 1.8 + 1.8 + 0.35-rc4 + 1.2.3 + 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 1b7b8f0f90..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 01:18: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 29b6faca34..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 01:18: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 791a3a2776..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 01:18:00"} + {"message":"hello user1, it's 23:18:00"} diff --git a/rsocket/pom.xml b/rsocket/pom.xml index 8b04a31583..d2182719c2 100644 --- a/rsocket/pom.xml +++ b/rsocket/pom.xml @@ -4,51 +4,61 @@ rsocket 0.0.1-SNAPSHOT rsocket + jar - + com.baeldung parent-modules 1.0.0-SNAPSHOT - jar - + io.rsocket rsocket-core - 0.11.13 + ${rsocket.version} io.rsocket rsocket-transport-netty - 0.11.13 + ${rsocket.version} junit junit - 4.12 + ${junit.version} test org.hamcrest hamcrest-core - 1.3 + ${hamcrest.version} test ch.qos.logback logback-classic - 1.2.3 + ${logback.version} ch.qos.logback logback-core - 1.2.3 + ${logback.version} org.slf4j slf4j-api - 1.7.25 + ${slf4j-api.version} - \ No newline at end of file + + + 1.8 + 1.8 + 3.0.1 + 0.11.13 + 1.3 + 1.2.3 + 1.7.25 + + diff --git a/rule-engines/easy-rules/pom.xml b/rule-engines/easy-rules/pom.xml index 5b88ce4e94..369451c56c 100644 --- a/rule-engines/easy-rules/pom.xml +++ b/rule-engines/easy-rules/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -23,4 +24,4 @@ 3.0.0 - \ No newline at end of file + diff --git a/rule-engines/openl-tablets/pom.xml b/rule-engines/openl-tablets/pom.xml index 3bd6055fc9..b19ec8d3f1 100644 --- a/rule-engines/openl-tablets/pom.xml +++ b/rule-engines/openl-tablets/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -29,4 +30,4 @@ 5.19.4 - \ No newline at end of file + diff --git a/rule-engines/pom.xml b/rule-engines/pom.xml new file mode 100644 index 0000000000..2ce82ed22b --- /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/rule-engines/rulebook/pom.xml b/rule-engines/rulebook/pom.xml index 90b5e55417..5e0b900bd9 100644 --- a/rule-engines/rulebook/pom.xml +++ b/rule-engines/rulebook/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -24,4 +25,4 @@ 0.6.2 - \ No newline at end of file + diff --git a/rxjava-2/README.md b/rxjava-2/README.md index d0bdeec684..4182f3fa00 100644 --- a/rxjava-2/README.md +++ b/rxjava-2/README.md @@ -2,8 +2,8 @@ - [RxJava and Error Handling](http://www.baeldung.com/rxjava-error-handling) - [RxJava 2 – Flowable](http://www.baeldung.com/rxjava-2-flowable) -- [RxJava 2 - Completable](http://www.baeldung.com/rxjava-completable) - [RxJava Maybe](http://www.baeldung.com/rxjava-maybe) - [Introduction to RxRelay for RxJava](http://www.baeldung.com/rx-relay) - [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable) - [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables) +- [RxJava Hooks](https://www.baeldung.com/rxjava-hooks) diff --git a/rxjava-2/pom.xml b/rxjava-2/pom.xml index 3038c20037..47d16ec8dd 100644 --- a/rxjava-2/pom.xml +++ b/rxjava-2/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 - rxjava-2 + rxjava-2 1.0-SNAPSHOT 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 new file mode 100644 index 0000000000..dd4287a4a9 --- /dev/null +++ b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java @@ -0,0 +1,244 @@ +package com.baeldung.rxjava; + +import static org.junit.Assert.assertTrue; + +import org.junit.After; +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 { + + 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() { + + RxJavaPlugins.setOnCompletableAssembly(completable -> { + hookCalled = true; + return completable; + }); + Completable.fromSingle(Single.just(1)); + assertTrue(hookCalled); + } + + @Test + public void givenCompletable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { + hookCalled = true; + return observer; + }); + + Completable.fromSingle(Single.just(1)) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenObservable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnObservableAssembly(observable -> { + hookCalled = true; + return observable; + }); + + Observable.range(1, 10); + assertTrue(hookCalled); + } + + @Test + public void givenObservable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { + hookCalled = true; + return observer; + }); + + Observable.range(1, 10) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { + hookCalled = true; + return connectableObservable; + }); + + ConnectableObservable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); + } + + @Test + public void givenFlowable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnFlowableAssembly(flowable -> { + hookCalled = true; + return flowable; + }); + + Flowable.range(1, 10); + assertTrue(hookCalled); + } + + @Test + public void givenFlowable_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { + hookCalled = true; + return observer; + }); + + Flowable.range(1, 10) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { + hookCalled = true; + return connectableFlowable; + }); + + ConnectableFlowable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); + } + + @Test + public void givenParallel_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { + hookCalled = true; + return parallelFlowable; + }); + + Flowable.range(1, 10) + .parallel(); + assertTrue(hookCalled); + } + + @Test + public void givenMaybe_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnMaybeAssembly(maybe -> { + hookCalled = true; + return maybe; + }); + + Maybe.just(1); + assertTrue(hookCalled); + } + + @Test + public void givenMaybe_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { + hookCalled = true; + return observer; + }); + + Maybe.just(1) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenSingle_whenAssembled_shouldExecuteTheHook() { + + RxJavaPlugins.setOnSingleAssembly(single -> { + hookCalled = true; + return single; + }); + + Single.just(1); + assertTrue(hookCalled); + } + + @Test + public void givenSingle_whenSubscribed_shouldExecuteTheHook() { + + RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { + hookCalled = true; + return observer; + }); + + Single.just(1) + .test(); + assertTrue(hookCalled); + } + + @Test + public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() { + + RxJavaPlugins.setScheduleHandler((runnable) -> { + hookCalled = true; + return runnable; + }); + + 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() { + + 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); + } + + @After + public void reset() { + initHookCalled = false; + hookCalled = false; + RxJavaPlugins.reset(); + } +} diff --git a/rxjava/pom.xml b/rxjava/pom.xml index 596a5196da..85106d1127 100644 --- a/rxjava/pom.xml +++ b/rxjava/pom.xml @@ -62,7 +62,6 @@ 1.0.0 1.1.1 1.7.0 - 1.4.196 \ No newline at end of file diff --git a/saas/pom.xml b/saas/pom.xml index 2abc932497..35de34ea72 100644 --- a/saas/pom.xml +++ b/saas/pom.xml @@ -4,8 +4,8 @@ com.baeldung saas 0.1.0-SNAPSHOT - jar saas + jar com.baeldung diff --git a/software-security/sql-injection-samples/.gitignore b/software-security/sql-injection-samples/.gitignore new file mode 100644 index 0000000000..82eca336e3 --- /dev/null +++ b/software-security/sql-injection-samples/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file 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) diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml new file mode 100644 index 0000000000..5c3256319e --- /dev/null +++ b/software-security/sql-injection-samples/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + com.baeldung + sql-injection-samples + 0.0.1-SNAPSHOT + sql-injection-samples + Sample SQL Injection tests + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.apache.derby + derby + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.projectlombok + lombok + provided + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.hibernate + hibernate-jpamodelgen + + + org.springframework.boot + spring-boot-devtools + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ 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 new file mode 100644 index 0000000000..c7285e5fd3 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -0,0 +1,298 @@ +/** + * + */ +package com.baeldung.examples.security.sql; + +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; + +/** + * @author Philippe + * + */ +@Component +public class AccountDAO { + + private final DataSource dataSource; + private final EntityManager em; + + public AccountDAO(DataSource dataSource, EntityManager em) { + this.dataSource = dataSource; + this.em = em; + } + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List unsafeFindAccountsByCustomerId(String customerId) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = '" + customerId + "'"; + + try (Connection c = dataSource.getConnection(); + ResultSet rs = c.createStatement() + .executeQuery(sql)) { + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customer_id")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * 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 + * + * @param customerId + * @return + */ + public List safeFindAccountsByCustomerId(String customerId) { + + 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); + 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(); + + accounts.add(acc); + } + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * 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) { + + 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 { + throw new IllegalArgumentException("Nice try!"); + } + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { + + p.setString(1, customerId); + 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(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + + 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 Long wrongCountRecordsByTableName(String tableName) { + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement("select count(*) from ?")) { + + p.setString(1, tableName); + ResultSet rs = p.executeQuery(); + rs.next(); + return rs.getLong(1); + + } 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/java/com/baeldung/examples/security/sql/AccountDTO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java new file mode 100644 index 0000000000..2e6fa04af4 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java @@ -0,0 +1,16 @@ +package com.baeldung.examples.security.sql; + +import java.math.BigDecimal; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class AccountDTO { + + 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/SqlInjectionSamplesApplication.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java new file mode 100644 index 0000000000..c1083ae3de --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.examples.security.sql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SqlInjectionSamplesApplication { + + public static void main(String[] args) { + SpringApplication.run(SqlInjectionSamplesApplication.class, args); + } + +} + diff --git a/software-security/sql-injection-samples/src/main/resources/application.properties b/software-security/sql-injection-samples/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/resources/application.properties @@ -0,0 +1 @@ + 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 new file mode 100644 index 0000000000..f61b738abc --- /dev/null +++ b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -0,0 +1,92 @@ +package com.baeldung.examples.security.sql; + +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.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.examples.security.sql.AccountDAO; +import com.baeldung.examples.security.sql.AccountDTO; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({ "test" }) +public class SqlInjectionSamplesApplicationUnitTest { + + @Autowired + private AccountDAO target; + + @Test + public void givenAVulnerableMethod_whenValidCustomerId_thenReturnSingleAccount() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(1); + } + + @Test + public void givenAVulnerableMethod_whenHackedCustomerId_thenReturnAllAccounts() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + 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() { + + List accounts = target.safeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + 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 = 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 new file mode 100644 index 0000000000..3af3f58bff --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/application-test.yml @@ -0,0 +1,18 @@ +# +# Test profile configuration +# +spring: + liquibase: + change-log: db/changelog/db.changelog-master.xml + + jpa: + hibernate: + ddl-auto: none + + datasource: + initialization-mode: embedded + +logging: + level: + sql: DEBUG + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/resources/data.sql b/software-security/sql-injection-samples/src/test/resources/data.sql new file mode 100644 index 0000000000..586618a07f --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/data.sql @@ -0,0 +1,4 @@ +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C1','0001',1,1000.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C2','0002',1,500.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C3','0003',1,501.00); + diff --git a/software-security/sql-injection-samples/src/test/resources/schema.sql b/software-security/sql-injection-samples/src/test/resources/schema.sql new file mode 100644 index 0000000000..cfc4c44f98 --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/schema.sql @@ -0,0 +1,7 @@ +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), + balance decimal(16,4) +); 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) diff --git a/spf4j/pom.xml b/spf4j/pom.xml new file mode 100644 index 0000000000..43a8028dc4 --- /dev/null +++ b/spf4j/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + com.baeldung.spf4j + spf4j + spf4j + pom + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + spf4j-core-app + spf4j-aspects-app + + + diff --git a/spf4j/spf4j-aspects-app/pom.xml b/spf4j/spf4j-aspects-app/pom.xml new file mode 100644 index 0000000000..1c707f4d87 --- /dev/null +++ b/spf4j/spf4j-aspects-app/pom.xml @@ -0,0 +1,87 @@ + + 4.0.0 + spf4j-aspects-app + 0.0.1-SNAPSHOT + jar + spf4j-aspects-app + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + + + org.spf4j + spf4j-aspects + ${spf4j.version} + + + org.spf4j + spf4j-ui + ${spf4j.version} + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + + spf4j-aspects-app + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/dependency-jars/ + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.baeldung.spf4j.aspects.App + true + dependency-jars/ + + + + + + + + + UTF-8 + 8.6.10 + 1.7.21 + + diff --git a/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/App.java b/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/App.java new file mode 100644 index 0000000000..6d74292c75 --- /dev/null +++ b/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/App.java @@ -0,0 +1,28 @@ +package com.baeldung.spf4j.aspects; + +import java.util.Random; + +import org.spf4j.annotations.PerformanceMonitor; + +public class App { + + public static void main(String[] args) throws InterruptedException { + Spf4jConfig.initialize(); + Random random = new Random(); + for (int i = 0; i < 100; i++) { + long numberToCheck = random.nextInt(999_999_999 - 100_000_000 + 1) + 100_000_000; + isPrimeNumber(numberToCheck); + } + System.exit(0); + } + + @PerformanceMonitor(warnThresholdMillis = 1, errorThresholdMillis = 100, recorderSource = Spf4jConfig.RecorderSourceForIsPrimeNumber.class) + public static boolean isPrimeNumber(long number) { + for (long i = 2; i <= number / 2; i++) { + if (number % i == 0) + return false; + } + return true; + } + +} diff --git a/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/Spf4jConfig.java b/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/Spf4jConfig.java new file mode 100644 index 0000000000..a12213f0cd --- /dev/null +++ b/spf4j/spf4j-aspects-app/src/main/java/com/baeldung/spf4j/aspects/Spf4jConfig.java @@ -0,0 +1,37 @@ +package com.baeldung.spf4j.aspects; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spf4j.annotations.RecorderSourceInstance; +import org.spf4j.perf.MeasurementRecorderSource; +import org.spf4j.perf.impl.RecorderFactory; + +public class Spf4jConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static void initialize() { + String tsDbFile = System.getProperty("user.dir") + File.separator + "spf4j-performance-monitoring.tsdb2"; + String tsTextFile = System.getProperty("user.dir") + File.separator + "spf4j-performance-monitoring.txt"; + + LOGGER.info("\nTime Series DB (TSDB) : {}\nTime Series text file : {}", tsDbFile, tsTextFile); + System.setProperty("spf4j.perf.ms.config", "TSDB@" + tsDbFile + "," + "TSDB_TXT@" + tsTextFile); + } + + public static final class RecorderSourceForIsPrimeNumber extends RecorderSourceInstance { + public static final MeasurementRecorderSource INSTANCE; + + static { + Object forWhat = App.class + " isPrimeNumber"; + String unitOfMeasurement = "ms"; + int sampleTimeMillis = 1_000; + int factor = 10; + int lowerMagnitude = 0; + int higherMagnitude = 4; + int quantasPerMagnitude = 10; + INSTANCE = RecorderFactory.createScalableQuantizedRecorderSource(forWhat, unitOfMeasurement, + sampleTimeMillis, factor, lowerMagnitude, higherMagnitude, quantasPerMagnitude); + } + } +} diff --git a/spf4j/spf4j-aspects-app/src/main/resources/META-INF/aop.xml b/spf4j/spf4j-aspects-app/src/main/resources/META-INF/aop.xml new file mode 100644 index 0000000000..1643f5fba9 --- /dev/null +++ b/spf4j/spf4j-aspects-app/src/main/resources/META-INF/aop.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/spf4j/spf4j-aspects-app/src/main/resources/logback.xml b/spf4j/spf4j-aspects-app/src/main/resources/logback.xml new file mode 100644 index 0000000000..4677fac9bf --- /dev/null +++ b/spf4j/spf4j-aspects-app/src/main/resources/logback.xml @@ -0,0 +1,11 @@ + + + + [%level] %msg%n + + + + + + \ No newline at end of file diff --git a/spf4j/spf4j-core-app/pom.xml b/spf4j/spf4j-core-app/pom.xml new file mode 100644 index 0000000000..9f490d9f06 --- /dev/null +++ b/spf4j/spf4j-core-app/pom.xml @@ -0,0 +1,87 @@ + + 4.0.0 + spf4j-core-app + 0.0.1-SNAPSHOT + jar + spf4j-core-app + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../ + + + + + org.spf4j + spf4j-core + ${spf4j.version} + + + org.spf4j + spf4j-ui + ${spf4j.version} + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + + spf4j-core-app + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/dependency-jars/ + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.baeldung.spf4j.core.App + true + dependency-jars/ + + + + + + + + + UTF-8 + 8.6.10 + 1.7.21 + + diff --git a/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/App.java b/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/App.java new file mode 100644 index 0000000000..fa107d8e4f --- /dev/null +++ b/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/App.java @@ -0,0 +1,34 @@ +package com.baeldung.spf4j.core; + +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spf4j.perf.MeasurementRecorder; + +public class App { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static void main(String[] args) throws InterruptedException { + Spf4jConfig.initialize(); + MeasurementRecorder measurementRecorder = Spf4jConfig.getMeasurementRecorder(App.class + " isPrimeNumber"); + Random random = new Random(); + for (int i = 0; i < 100; i++) { + long numberToCheck = random.nextInt(999_999_999 - 100_000_000 + 1) + 100_000_000; + long startTime = System.currentTimeMillis(); + boolean isPrime = isPrimeNumber(numberToCheck); + measurementRecorder.record(System.currentTimeMillis() - startTime); + LOGGER.info("{}. {} is prime? {}", i + 1, numberToCheck, isPrime); + } + System.exit(0); + } + + private static boolean isPrimeNumber(long number) { + for (long i = 2; i <= number / 2; i++) { + if (number % i == 0) + return false; + } + return true; + } + +} diff --git a/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/Spf4jConfig.java b/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/Spf4jConfig.java new file mode 100644 index 0000000000..0f806e1576 --- /dev/null +++ b/spf4j/spf4j-core-app/src/main/java/com/baeldung/spf4j/core/Spf4jConfig.java @@ -0,0 +1,31 @@ +package com.baeldung.spf4j.core; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spf4j.perf.MeasurementRecorder; +import org.spf4j.perf.impl.RecorderFactory; + +public class Spf4jConfig { + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public static void initialize() { + String tsDbFile = System.getProperty("user.dir") + File.separator + "spf4j-performance-monitoring.tsdb2"; + String tsTextFile = System.getProperty("user.dir") + File.separator + "spf4j-performance-monitoring.txt"; + + LOGGER.info("\nTime Series DB (TSDB) : {}\nTime Series text file : {}", tsDbFile, tsTextFile); + System.setProperty("spf4j.perf.ms.config", "TSDB@" + tsDbFile + "," + "TSDB_TXT@" + tsTextFile); + } + + public static MeasurementRecorder getMeasurementRecorder(Object forWhat) { + String unitOfMeasurement = "ms"; + int sampleTimeMillis = 1_000; + int factor = 10; + int lowerMagnitude = 0; + int higherMagnitude = 4; + int quantasPerMagnitude = 10; + + return RecorderFactory.createScalableQuantizedRecorder(forWhat, unitOfMeasurement, sampleTimeMillis, factor, lowerMagnitude, higherMagnitude, quantasPerMagnitude); + } +} diff --git a/spf4j/spf4j-core-app/src/main/resources/logback.xml b/spf4j/spf4j-core-app/src/main/resources/logback.xml new file mode 100644 index 0000000000..4677fac9bf --- /dev/null +++ b/spf4j/spf4j-core-app/src/main/resources/logback.xml @@ -0,0 +1,11 @@ + + + + [%level] %msg%n + + + + + + \ No newline at end of file diff --git a/spring-4/README.md b/spring-4/README.md index 402557eb41..57cb8c3eeb 100644 --- a/spring-4/README.md +++ b/spring-4/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [A Guide to Flips for Spring](http://www.baeldung.com/flips-spring) - [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) +- [Spring JSON-P with Jackson](http://www.baeldung.com/spring-jackson-jsonp) diff --git a/spring-4/pom.xml b/spring-4/pom.xml index 78939bba95..59b74782ec 100644 --- a/spring-4/pom.xml +++ b/spring-4/pom.xml @@ -3,8 +3,8 @@ 4.0.0 spring-4 spring-4 - jar spring-4 + jar parent-boot-1 @@ -52,6 +52,21 @@ provided + + javax.servlet + jstl + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + @@ -71,9 +86,8 @@ + com.baeldung.flips.ApplicationConfig 1.0.1 - 1.16.18 - 1.4.197 diff --git a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java index 7001aeb991..1bd6ffa336 100644 --- a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java +++ b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java @@ -3,9 +3,15 @@ package com.baeldung.flips; import org.flips.describe.config.FlipWebContextConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.context.annotation.Import; -@SpringBootApplication +@SpringBootApplication(exclude = { + DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class }) @Import(FlipWebContextConfiguration.class) public class ApplicationConfig { diff --git a/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java new file mode 100644 index 0000000000..a8f3c0e102 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java @@ -0,0 +1,27 @@ +package com.baeldung.jsonp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication(exclude = { + DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class }) +@PropertySource("classpath:jsonp-application.properties") +public class JsonPApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(JsonPApplication.class); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(JsonPApplication.class, args); + } +} diff --git a/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java new file mode 100644 index 0000000000..b11a216e52 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java @@ -0,0 +1,38 @@ +package com.baeldung.jsonp.model; + +public class Company { + + private long id; + private String name; + + public Company() { + super(); + } + + public Company(final long id, final String name) { + this.id = id; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + @Override + public String toString() { + return "Company [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java new file mode 100644 index 0000000000..8710359365 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java @@ -0,0 +1,27 @@ +package com.baeldung.jsonp.web.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.baeldung.jsonp.model.Company; + +@Controller +public class CompanyController { + + @RequestMapping(value = "/companyResponseBody", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Company getCompanyResponseBody() { + final Company company = new Company(2, "ABC"); + return company; + } + + @RequestMapping(value = "/companyResponseEntity", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getCompanyResponseEntity() { + final Company company = new Company(3, "123"); + return new ResponseEntity(company, HttpStatus.OK); + } +} diff --git a/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java new file mode 100644 index 0000000000..8469e19458 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java @@ -0,0 +1,13 @@ +package com.baeldung.jsonp.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class IndexController { + + @RequestMapping() + public String retrieveIndex() { + return "index"; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java similarity index 53% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java rename to spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java index 7b2c6870df..be7c65cb1e 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java @@ -1,8 +1,11 @@ -package com.baeldung.web.controller.advice; +package com.baeldung.jsonp.web.controller.advice; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; +// AbstractJsonpResponseBodyAdvice was deprecated in favor of configuring CORS properly +// We still want to cover the usage of JSON-P in our articles, therefore we don't care that it was deprecated. +@SuppressWarnings("deprecation") @ControllerAdvice public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice { diff --git a/spring-4/src/main/resources/application.properties b/spring-4/src/main/resources/application.properties index 274896be15..e67700b7be 100644 --- a/spring-4/src/main/resources/application.properties +++ b/spring-4/src/main/resources/application.properties @@ -2,4 +2,4 @@ feature.foo.by.id=Y feature.new.foo=Y last.active.after=2018-03-14T00:00:00Z first.active.after=2999-03-15T00:00:00Z -logging.level.org.flips=info \ No newline at end of file +logging.level.org.flips=info diff --git a/spring-4/src/main/resources/jsonp-application.properties b/spring-4/src/main/resources/jsonp-application.properties new file mode 100644 index 0000000000..94e7fcc026 --- /dev/null +++ b/spring-4/src/main/resources/jsonp-application.properties @@ -0,0 +1,2 @@ +spring.mvc.view.prefix=/WEB-INF/jsp/ +spring.mvc.view.suffix=.jsp diff --git a/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..fa5498c966 --- /dev/null +++ b/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,66 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1" %> + + + + + Company Data + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 9dfac2bd9e..d646e22511 100644 --- a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -2,13 +2,16 @@ 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 org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; import com.baeldung.flips.ApplicationConfig; -@RunWith(SpringRunner.class) -@SpringBootTest(classes = ApplicationConfig.class) + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationConfig.class) +@WebAppConfiguration public class SpringContextIntegrationTest { @Test diff --git a/spring-5-data-reactive/README.md b/spring-5-data-reactive/README.md index f8886ac18b..f3205c23bc 100644 --- a/spring-5-data-reactive/README.md +++ b/spring-5-data-reactive/README.md @@ -6,3 +6,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles - [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) - [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) +- [Spring Data MongoDB Tailable Cursors](https://www.baeldung.com/spring-data-mongodb-tailable-cursors) diff --git a/spring-5-data-reactive/pom.xml b/spring-5-data-reactive/pom.xml index aa73cf11ae..8c16851de0 100644 --- a/spring-5-data-reactive/pom.xml +++ b/spring-5-data-reactive/pom.xml @@ -63,6 +63,11 @@ spring-boot-starter-test test + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java new file mode 100644 index 0000000000..8b2511a8f3 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.tailablecursor; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LogsCounterApplication { + public static void main(String[] args) { + SpringApplication.run(LogsCounterApplication.class, args); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java new file mode 100644 index 0000000000..717a367751 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java @@ -0,0 +1,21 @@ +package com.baeldung.tailablecursor.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Log { + @Id + private String id; + private String service; + private LogLevel level; + private String message; +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java new file mode 100644 index 0000000000..6826fbffd3 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java @@ -0,0 +1,5 @@ +package com.baeldung.tailablecursor.domain; + +public enum LogLevel { + ERROR, WARN, INFO +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java new file mode 100644 index 0000000000..dce11c548c --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.tailablecursor.repository; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import org.springframework.data.mongodb.repository.Tailable; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import reactor.core.publisher.Flux; + +public interface LogsRepository extends ReactiveCrudRepository { + @Tailable + Flux findByLevel(LogLevel level); +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java new file mode 100644 index 0000000000..c243e64f97 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java @@ -0,0 +1,62 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainer; +import org.springframework.data.mongodb.core.messaging.MessageListener; +import org.springframework.data.mongodb.core.messaging.MessageListenerContainer; +import org.springframework.data.mongodb.core.messaging.TailableCursorRequest; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +@Slf4j +public class ErrorLogsCounter implements LogsCounter { + + private static final String LEVEL_FIELD_NAME = "level"; + + private final String collectionName; + private final MessageListenerContainer container; + + private final AtomicInteger counter = new AtomicInteger(); + + public ErrorLogsCounter(MongoTemplate mongoTemplate, + String collectionName) { + this.collectionName = collectionName; + this.container = new DefaultMessageListenerContainer(mongoTemplate); + + container.start(); + TailableCursorRequest request = getTailableCursorRequest(); + container.register(request, Log.class); + } + + @SuppressWarnings("unchecked") + private TailableCursorRequest getTailableCursorRequest() { + MessageListener listener = message -> { + log.info("ERROR log received: {}", message.getBody()); + counter.incrementAndGet(); + }; + + return TailableCursorRequest.builder() + .collection(collectionName) + .filter(query(where(LEVEL_FIELD_NAME).is(LogLevel.ERROR))) + .publishTo(listener) + .build(); + } + + @Override + public int count() { + return counter.get(); + } + + @PreDestroy + public void close() { + container.stop(); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java new file mode 100644 index 0000000000..29301bffec --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java @@ -0,0 +1,36 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +@Slf4j +public class InfoLogsCounter implements LogsCounter { + + private final AtomicInteger counter = new AtomicInteger(); + private final Disposable subscription; + + public InfoLogsCounter(LogsRepository repository) { + Flux stream = repository.findByLevel(LogLevel.INFO); + this.subscription = stream.subscribe(logEntity -> { + log.info("INFO log received: " + logEntity); + counter.incrementAndGet(); + }); + } + + @Override + public int count() { + return this.counter.get(); + } + + @PreDestroy + public void close() { + this.subscription.dispose(); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java new file mode 100644 index 0000000000..e14a3eadd7 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java @@ -0,0 +1,5 @@ +package com.baeldung.tailablecursor.service; + +public interface LogsCounter { + int count(); +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java new file mode 100644 index 0000000000..2dff8e8e40 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java @@ -0,0 +1,41 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +@Slf4j +public class WarnLogsCounter implements LogsCounter { + + private static final String LEVEL_FIELD_NAME = "level"; + + private final AtomicInteger counter = new AtomicInteger(); + private final Disposable subscription; + + public WarnLogsCounter(ReactiveMongoOperations template) { + Flux stream = template.tail(query(where(LEVEL_FIELD_NAME).is(LogLevel.WARN)), Log.class); + subscription = stream.subscribe(logEntity -> { + log.warn("WARN log received: " + logEntity); + counter.incrementAndGet(); + }); + } + + @Override + public int count() { + return counter.get(); + } + + @PreDestroy + public void close() { + subscription.dispose(); + } +} diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java similarity index 97% rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java index f425826dce..d4b1d0eeda 100644 --- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java +++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java @@ -17,7 +17,7 @@ import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) -public class AccountCrudRepositoryIntegrationTest { +public class AccountCrudRepositoryManualTest { @Autowired AccountCrudRepository repository; diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java similarity index 97% rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java index bfa6a789b2..2ca075aa5e 100644 --- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java +++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java @@ -19,7 +19,7 @@ import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatc @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) -public class AccountMongoRepositoryIntegrationTest { +public class AccountMongoRepositoryManualTest { @Autowired AccountMongoRepository repository; diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java similarity index 97% rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java index e9b3eb1c40..d91acd24e2 100644 --- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java +++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java @@ -15,7 +15,7 @@ import static org.junit.Assert.assertNotNull; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) -public class AccountRxJavaRepositoryIntegrationTest { +public class AccountRxJavaRepositoryManualTest { @Autowired AccountRxJavaRepository repository; diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java similarity index 97% rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java index 373da0e393..5fa0e39317 100644 --- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java +++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java @@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.*; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) -public class AccountTemplateOperationsIntegrationTest { +public class AccountTemplateOperationsManualTest { @Autowired AccountTemplateOperations accountTemplate; diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java new file mode 100644 index 0000000000..5e20d3ec79 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java @@ -0,0 +1,112 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CreateCollectionOptions; +import de.flapdoodle.embed.mongo.MongodExecutable; +import de.flapdoodle.embed.mongo.MongodProcess; +import de.flapdoodle.embed.mongo.MongodStarter; +import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; +import de.flapdoodle.embed.mongo.config.Net; +import de.flapdoodle.embed.mongo.distribution.Version; +import de.flapdoodle.embed.process.runtime.Network; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.util.SocketUtils; + +import java.io.IOException; +import java.util.stream.IntStream; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class ErrorLogsCounterManualTest { + + private static final String SERVER = "localhost"; + private static final int PORT = SocketUtils.findAvailableTcpPort(10000); + private static final String DB_NAME = "test"; + private static final String COLLECTION_NAME = Log.class.getName().toLowerCase(); + + private static final MongodStarter starter = MongodStarter.getDefaultInstance(); + private static final int MAX_DOCUMENTS_IN_COLLECTION = 3; + + private ErrorLogsCounter errorLogsCounter; + private MongodExecutable mongodExecutable; + private MongodProcess mongoDaemon; + private MongoDatabase db; + + @Before + public void setup() throws Exception { + MongoTemplate mongoTemplate = initMongoTemplate(); + + MongoCollection collection = createCappedCollection(); + + persistDocument(collection, -1, LogLevel.ERROR, "my-service", "Initial log"); + + errorLogsCounter = new ErrorLogsCounter(mongoTemplate, COLLECTION_NAME); + Thread.sleep(1000L); // wait for initialization + } + + private MongoTemplate initMongoTemplate() throws IOException { + mongodExecutable = starter.prepare(new MongodConfigBuilder() + .version(Version.Main.PRODUCTION) + .net(new Net(SERVER, PORT, Network.localhostIsIPv6())) + .build()); + mongoDaemon = mongodExecutable.start(); + + MongoClient mongoClient = new MongoClient(SERVER, PORT); + db = mongoClient.getDatabase(DB_NAME); + + return new MongoTemplate(mongoClient, DB_NAME); + } + + private MongoCollection createCappedCollection() { + db.createCollection(COLLECTION_NAME, new CreateCollectionOptions() + .capped(true) + .sizeInBytes(100000) + .maxDocuments(MAX_DOCUMENTS_IN_COLLECTION)); + return db.getCollection(COLLECTION_NAME); + } + + private void persistDocument(MongoCollection collection, + int i, LogLevel level, String service, String message) { + Document logMessage = new Document(); + logMessage.append("_id", i); + logMessage.append("level", level.toString()); + logMessage.append("service", service); + logMessage.append("message", message); + collection.insertOne(logMessage); + } + + @After + public void tearDown() { + errorLogsCounter.close(); + mongoDaemon.stop(); + mongodExecutable.stop(); + } + + @Test + public void whenErrorLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + MongoCollection collection = db.getCollection(COLLECTION_NAME); + + IntStream.range(1, 10) + .forEach(i -> persistDocument(collection, + i, + i > 5 ? LogLevel.ERROR : LogLevel.INFO, + "service" + i, + "Message from service " + i) + ); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(collection.countDocuments(), is((long) MAX_DOCUMENTS_IN_COLLECTION)); + assertThat(errorLogsCounter.count(), is(5)); + } + +} diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java new file mode 100644 index 0000000000..cd8bd68257 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.LogsCounterApplication; +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +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.mongodb.core.CollectionOptions; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = LogsCounterApplication.class) +@Slf4j +public class InfoLogsCounterManualTest { + @Autowired + private LogsRepository repository; + + @Autowired + private ReactiveMongoTemplate template; + + @Before + public void setUp() { + createCappedCollectionUsingReactiveMongoTemplate(template); + + persistDocument(Log.builder() + .level(LogLevel.INFO) + .service("Service 2") + .message("Initial INFO message") + .build()); + } + + private void createCappedCollectionUsingReactiveMongoTemplate(ReactiveMongoTemplate reactiveMongoTemplate) { + reactiveMongoTemplate.dropCollection(Log.class).block(); + reactiveMongoTemplate.createCollection(Log.class, CollectionOptions.empty() + .maxDocuments(5) + .size(1024 * 1024L) + .capped()).block(); + } + + private void persistDocument(Log log) { + repository.save(log).block(); + } + + @Test + public void wheInfoLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + InfoLogsCounter infoLogsCounter = new InfoLogsCounter(repository); + + Thread.sleep(1000L); // wait for initialization + + Flux.range(0,10) + .map(i -> Log.builder() + .level(i > 5 ? LogLevel.WARN : LogLevel.INFO) + .service("some-service") + .message("some log message") + .build()) + .map(entity -> repository.save(entity).subscribe()) + .blockLast(); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(infoLogsCounter.count(), is(7)); + infoLogsCounter.close(); + } +} \ No newline at end of file diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java new file mode 100644 index 0000000000..79d94b6784 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.LogsCounterApplication; +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +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.mongodb.core.CollectionOptions; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = LogsCounterApplication.class) +@Slf4j +public class WarnLogsCounterManualTest { + @Autowired + private LogsRepository repository; + + @Autowired + private ReactiveMongoTemplate template; + + @Before + public void setUp() { + createCappedCollectionUsingReactiveMongoTemplate(template); + + persistDocument(Log.builder() + .level(LogLevel.WARN) + .service("Service 1") + .message("Initial Warn message") + .build()); + } + + private void createCappedCollectionUsingReactiveMongoTemplate(ReactiveMongoTemplate reactiveMongoTemplate) { + reactiveMongoTemplate.dropCollection(Log.class).block(); + reactiveMongoTemplate.createCollection(Log.class, CollectionOptions.empty() + .maxDocuments(5) + .size(1024 * 1024L) + .capped()).block(); + } + + private void persistDocument(Log log) { + repository.save(log).block(); + } + + @Test + public void whenWarnLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + WarnLogsCounter warnLogsCounter = new WarnLogsCounter(template); + + Thread.sleep(1000L); // wait for initialization + + Flux.range(0,10) + .map(i -> Log.builder() + .level(i > 5 ? LogLevel.WARN : LogLevel.INFO) + .service("some-service") + .message("some log message") + .build()) + .map(entity -> repository.save(entity).subscribe()) + .blockLast(); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(warnLogsCounter.count(), is(5)); + warnLogsCounter.close(); + } +} \ No newline at end of file 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) diff --git a/spring-5-mvc/pom.xml b/spring-5-mvc/pom.xml index f5346a0fa0..5fb8f66f71 100644 --- a/spring-5-mvc/pom.xml +++ b/spring-5-mvc/pom.xml @@ -5,9 +5,9 @@ com.baeldung spring-5-mvc 0.0.1-SNAPSHOT - jar spring-5-mvc spring 5 MVC sample project about new features + jar com.baeldung diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 6e39743ed0..1b71815eb4 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -2,10 +2,9 @@ 4.0.0 - spring-5-reactive-client - jar spring-5-reactive-client + jar spring 5 sample project about new features diff --git a/spring-5-reactive-oauth/README.md b/spring-5-reactive-oauth/README.md index 0f27cf5d20..ec5176670b 100644 --- a/spring-5-reactive-oauth/README.md +++ b/spring-5-reactive-oauth/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Spring Security OAuth Login with WebFlux](https://www.baeldung.com/spring-oauth-login-webflux) +- [Spring WebClient and OAuth2 Support](https://www.baeldung.com/spring-webclient-oauth2) diff --git a/spring-5-reactive-oauth/pom.xml b/spring-5-reactive-oauth/pom.xml index 73809681f2..06ce817a02 100644 --- a/spring-5-reactive-oauth/pom.xml +++ b/spring-5-reactive-oauth/pom.xml @@ -2,27 +2,19 @@ 4.0.0 - com.baeldung.reactive.oauth spring-5-reactive-oauth 1.0.0-SNAPSHOT - jar - spring-5-reactive-oauth + jar WebFluc and Spring Security OAuth - org.springframework.boot - spring-boot-starter-parent - 2.1.0.RELEASE - - - - - UTF-8 - UTF-8 - 1.8 - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -62,11 +54,11 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 true **/*IntegrationTest.java + **/*LiveTest.java @@ -74,4 +66,10 @@ + + UTF-8 + UTF-8 + 2.1.0.RELEASE + + diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java index 602ded6b9e..b95517200e 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java @@ -3,11 +3,13 @@ package com.baeldung.reactive.oauth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.PropertySource; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; import org.springframework.web.reactive.function.client.WebClient; +@PropertySource("classpath:default-application.yml") @SpringBootApplication public class Spring5ReactiveOauthApplication { diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java new file mode 100644 index 0000000000..843d3f251f --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java @@ -0,0 +1,24 @@ +package com.baeldung.webclient.authorizationcodeclient; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +/** + * + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo + * + * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server + * + * @author rozagerardo + * + */ +@PropertySource("classpath:webclient-auth-code-client-application.properties") +@SpringBootApplication +public class OauthClientApplication { + + public static void main(String[] args) { + SpringApplication.run(OauthClientApplication.class, args); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java new file mode 100644 index 0000000000..884a3c145d --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.webclient.authorizationcodeclient.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; +import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + + @Bean + WebClient webClientForAuthorized(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) { + ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients); + return WebClient.builder() + .filter(oauth) + .build(); + } +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java new file mode 100644 index 0000000000..4271ae96cf --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java @@ -0,0 +1,22 @@ +package com.baeldung.webclient.authorizationcodeclient.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +public class WebSecurityConfig { + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .authenticated() + .and() + .oauth2Client() + .and() + .formLogin(); + return http.build(); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java new file mode 100644 index 0000000000..9994a1255a --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java @@ -0,0 +1,53 @@ +package com.baeldung.webclient.authorizationcodeclient.web; + +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; + +@RestController +public class ClientRestController { + + private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1"; + + @Autowired + WebClient webClient; + + @GetMapping("/auth-code") + Mono useOauthWithAuthCode() { + Mono retrievedResource = webClient.get() + .uri(RESOURCE_URI) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string); + } + + @GetMapping("/auth-code-annotated") + Mono useOauthWithAuthCodeAndAnnotation(@RegisteredOAuth2AuthorizedClient("bael") OAuth2AuthorizedClient authorizedClient) { + Mono retrievedResource = webClient.get() + .uri(RESOURCE_URI) + .attributes(oauth2AuthorizedClient(authorizedClient)) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string + ". Principal associated: " + authorizedClient.getPrincipalName() + ". Token will expire at: " + authorizedClient.getAccessToken() + .getExpiresAt()); + } + + @GetMapping("/auth-code-explicit-client") + Mono useOauthWithExpicitClient() { + Mono retrievedResource = webClient.get() + .uri(RESOURCE_URI) + .attributes(clientRegistrationId("bael")) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java new file mode 100644 index 0000000000..e71e549ea4 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java @@ -0,0 +1,24 @@ +package com.baeldung.webclient.authorizationcodelogin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +/** + * + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo + * + * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server + * + * @author rozagerardo + * + */ +@PropertySource("classpath:webclient-auth-code-login-application.properties") +@SpringBootApplication +public class OauthClientLoginApplication { + + public static void main(String[] args) { + SpringApplication.run(OauthClientLoginApplication.class, args); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java new file mode 100644 index 0000000000..15458cc60a --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java @@ -0,0 +1,31 @@ +package com.baeldung.webclient.authorizationcodelogin.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; +import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + + @Bean + @Primary + WebClient webClientForAuthorized(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) { + ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients); + oauth.setDefaultOAuth2AuthorizedClient(true); + return WebClient.builder() + .filter(oauth) + .build(); + } + + @Bean + WebClient otherWebClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) { + ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients); + return WebClient.builder() + .filter(oauth) + .build(); + } +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java new file mode 100644 index 0000000000..f45fc09222 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.webclient.authorizationcodelogin.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +public class WebSecurityConfig { + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .authenticated() + .and() + .oauth2Login(); + return http.build(); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java new file mode 100644 index 0000000000..24e5377f36 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java @@ -0,0 +1,68 @@ +package com.baeldung.webclient.authorizationcodelogin.web; + +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; +import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; + +@RestController +public class ClientRestController { + + private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1"; + + @Autowired + WebClient webClient; + + @Autowired + @Qualifier("otherWebClient") + WebClient otherWebClient; + + @GetMapping("/auth-code") + Mono useOauthWithAuthCode() { + Mono retrievedResource = webClient.get() + .uri(RESOURCE_URI) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string); + } + + @GetMapping("/auth-code-no-client") + Mono useOauthWithNoClient() { + // This call will fail, since we don't have the client properly set for this webClient + Mono retrievedResource = otherWebClient.get() + .uri(RESOURCE_URI) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string); + } + + @GetMapping("/auth-code-annotated") + Mono useOauthWithAuthCodeAndAnnotation(@RegisteredOAuth2AuthorizedClient("bael") OAuth2AuthorizedClient authorizedClient) { + Mono retrievedResource = otherWebClient.get() + .uri(RESOURCE_URI) + .attributes(oauth2AuthorizedClient(authorizedClient)) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string + ". Principal associated: " + authorizedClient.getPrincipalName() + ". Token will expire at: " + authorizedClient.getAccessToken() + .getExpiresAt()); + } + + @GetMapping("/auth-code-explicit-client") + Mono useOauthWithExpicitClient() { + Mono retrievedResource = otherWebClient.get() + .uri(RESOURCE_URI) + .attributes(clientRegistrationId("bael")) + .retrieve() + .bodyToMono(String.class); + return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java new file mode 100644 index 0000000000..4356581819 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java @@ -0,0 +1,24 @@ +package com.baeldung.webclient.clientcredentials; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo + * + * @author rozagerardo + * + */ +@PropertySource("classpath:webclient-client-credentials-oauth-application.properties") +@EnableScheduling +@SpringBootApplication +public class ClientCredentialsOauthApplication { + + public static void main(String[] args) { + SpringApplication.run(ClientCredentialsOauthApplication.class, args); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java new file mode 100644 index 0000000000..8ffc92b4cd --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java @@ -0,0 +1,22 @@ +package com.baeldung.webclient.clientcredentials.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; +import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + + @Bean + WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) { + ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository()); + oauth.setDefaultClientRegistrationId("bael"); + return WebClient.builder() + .filter(oauth) + .build(); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java new file mode 100644 index 0000000000..ef39222933 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java @@ -0,0 +1,31 @@ +package com.baeldung.webclient.clientcredentials.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +@Component +public class WebClientChonJob { + + Logger logger = LoggerFactory.getLogger(WebClientChonJob.class); + + private static final String RESOURCE_URI = "localhost:8082/spring-security-oauth-resource/foos/1"; + + @Autowired + private WebClient webClient; + + @Scheduled(fixedRate = 5000) + public void logResourceServiceResponse() { + + webClient.get() + .uri(RESOURCE_URI) + .retrieve() + .bodyToMono(String.class) + .map(string -> "We retrieved the following resource using Client Credentials Grant Type: " + string) + .subscribe(logger::info); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java new file mode 100644 index 0000000000..59a63355f7 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java @@ -0,0 +1,22 @@ +package com.baeldung.webclient.manualrequest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +/** + * + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo + * + * @author rozagerardo + * + */ +@PropertySource("classpath:webclient-manual-request-oauth-application.properties") +@SpringBootApplication +public class ManualRequestApplication { + + public static void main(String[] args) { + SpringApplication.run(ManualRequestApplication.class, args); + } + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java new file mode 100644 index 0000000000..51fc60821a --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.webclient.manualrequest.configure; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + + @Bean + public WebClient configureWebClient() { + return WebClient.builder() + .build(); + }; + +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java new file mode 100644 index 0000000000..1753681db8 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.webclient.manualrequest.configure; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +public class WebSecurityConfig { + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .permitAll(); + return http.build(); + } +} diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java new file mode 100644 index 0000000000..d54d811032 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java @@ -0,0 +1,63 @@ +package com.baeldung.webclient.manualrequest.web; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.Base64Utils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; + +import com.fasterxml.jackson.databind.JsonNode; +import com.nimbusds.oauth2.sdk.GrantType; + +import reactor.core.publisher.Mono; + +@RestController +public class ManualOauthRequestController { + + private static Logger logger = LoggerFactory.getLogger(ManualOauthRequestController.class); + + private static final String RESOURCE_ENDPOINT = "localhost:8082/spring-security-oauth-resource/foos/1"; + + @Value("${the.authorization.client-id}") + private String clientId; + + @Value("${the.authorization.client-secret}") + private String clientSecret; + + @Value("${the.authorization.token-uri}") + private String tokenUri; + + @Autowired + WebClient client; + + @GetMapping("/manual-request-oauth") + public Mono obtainSecuredResource() { + logger.info("Creating web client..."); + Mono resource = client.post() + .uri(tokenUri) + .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((clientId + ":" + clientSecret).getBytes())) + .body(BodyInserters.fromFormData(OAuth2ParameterNames.GRANT_TYPE, GrantType.CLIENT_CREDENTIALS.getValue())) + .retrieve() + .bodyToMono(JsonNode.class) + .flatMap(tokenResponse -> { + String accessTokenValue = tokenResponse.get("access_token") + .textValue(); + logger.info("Retrieved the following access token: {}", accessTokenValue); + return client.get() + .uri(RESOURCE_ENDPOINT) + .headers(h -> h.setBearerAuth(accessTokenValue)) + .retrieve() + .bodyToMono(String.class); + }); + logger.info("non-blocking Oauth calls registered..."); + return resource.map(res -> "Retrieved the resource using a manual approach: " + res); + + } + +} diff --git a/spring-5-reactive-oauth/src/main/resources/application.yml b/spring-5-reactive-oauth/src/main/resources/application.yml index e35e19b344..bec62fdd33 100644 --- a/spring-5-reactive-oauth/src/main/resources/application.yml +++ b/spring-5-reactive-oauth/src/main/resources/application.yml @@ -1,20 +1,3 @@ -spring: - security: - oauth2: - client: - registration: - google: - client-id: YOUR_APP_CLIENT_ID - client-secret: YOUR_APP_CLIENT_SECRET - custom: - client-id: fooClientIdPassword - client-secret: secret - scopes: read,foo - authorization-grant-type: authorization_code - redirect-uri-template: http://localhost:8080/login/oauth2/code/custom - provider: - custom: - authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize - token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token - user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra - user-name-attribute: user_name \ No newline at end of file +logging: + level: + root: DEBUG \ No newline at end of file diff --git a/spring-5-reactive-oauth/src/main/resources/default-application.yml b/spring-5-reactive-oauth/src/main/resources/default-application.yml new file mode 100644 index 0000000000..e35e19b344 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/default-application.yml @@ -0,0 +1,20 @@ +spring: + security: + oauth2: + client: + registration: + google: + client-id: YOUR_APP_CLIENT_ID + client-secret: YOUR_APP_CLIENT_SECRET + custom: + client-id: fooClientIdPassword + client-secret: secret + scopes: read,foo + authorization-grant-type: authorization_code + redirect-uri-template: http://localhost:8080/login/oauth2/code/custom + provider: + custom: + authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize + token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token + user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra + user-name-attribute: user_name \ No newline at end of file diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties new file mode 100644 index 0000000000..ac96aae6d6 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties @@ -0,0 +1,10 @@ +spring.security.oauth2.client.registration.bael.client-name=bael +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret +spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/authorize/oauth2/code/bael + +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token +spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize + +spring.security.user.password=pass diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties new file mode 100644 index 0000000000..e4dd0a532d --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties @@ -0,0 +1,10 @@ +spring.security.oauth2.client.registration.bael.client-name=bael +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret +spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/login/oauth2/code/bael + +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token +spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize +spring.security.oauth2.client.provider.bael.user-info-uri=http://localhost:8082/spring-security-oauth-resource/users/extra +spring.security.oauth2.client.provider.bael.user-name-attribute=user_name diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties new file mode 100644 index 0000000000..14c5b97605 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties @@ -0,0 +1,4 @@ +spring.security.oauth2.client.registration.bael.authorization-grant-type=client_credentials +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties new file mode 100644 index 0000000000..36ec3defd1 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties @@ -0,0 +1,3 @@ +the.authorization.client-id=fooClientIdPassword +the.authorization.client-secret=secret +the.authorization.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java new file mode 100644 index 0000000000..ef913ba055 --- /dev/null +++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java @@ -0,0 +1,52 @@ +package com.baeldung.webclient.clientcredentials; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collection; +import java.util.stream.Collectors; + +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 com.baeldung.webclient.clientcredentials.service.WebClientChonJob; +import com.baeldung.webclient.utils.ListAppender; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * + * Note: this Live test requires the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo + * + * @author rozagerardo + * + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { ClientCredentialsOauthApplication.class }) +public class OAuth2ClientCredentialsLiveTest { + + @Autowired + WebClientChonJob service; + + @Before + public void clearLogList() { + ListAppender.clearEventList(); + } + + @Test + public void givenFooWithNullId_whenProcessFoo_thenLogsWithDebugTrace() throws Exception { + service.logResourceServiceResponse(); + + Thread.sleep(3000); + + Collection allLoggedEntries = ListAppender.getEvents() + .stream() + .map(ILoggingEvent::getFormattedMessage) + .collect(Collectors.toList()); + assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("We retrieved the following resource using Client Credentials Grant Type: {\"id\"")); + } + +} diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java new file mode 100644 index 0000000000..2381264926 --- /dev/null +++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java @@ -0,0 +1,44 @@ +package com.baeldung.webclient.manualrequest; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; + +/** + * + * Note: this Live test requires not only the corresponding application running, + * but also the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo + * + * + * @author ger + * + */ +public class OAuth2ManualRequestLiveTest { + + private static final String BASE_URL = "http://localhost:8080"; + private static final String MANUAL_REQUEST_URI = "/manual-request-oauth"; + + private static WebTestClient client; + + @Before + public void setup() { + client = WebTestClient.bindToServer() + .baseUrl(BASE_URL) + .build(); + } + + @Test + public void whenRequestingDebugHookOn_thenObtainExpectedMessage() { + ResponseSpec response = client.get() + .uri(MANUAL_REQUEST_URI) + .exchange(); + + response.expectStatus() + .isOk() + .expectBody(String.class) + .value(Matchers.containsString("Retrieved the resource using a manual approach: {\"id\"")); + } + +} diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java new file mode 100644 index 0000000000..6f8fbe004a --- /dev/null +++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java @@ -0,0 +1,25 @@ +package com.baeldung.webclient.utils; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; + +public class ListAppender extends AppenderBase { + + static private List events = new ArrayList<>(); + + @Override + protected void append(ILoggingEvent eventObject) { + events.add(eventObject); + } + + public static List getEvents() { + return events; + } + + public static void clearEventList() { + events.clear(); + } +} \ No newline at end of file diff --git a/spring-5-reactive-oauth/src/test/resources/logback-test.xml b/spring-5-reactive-oauth/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..891c54bfd3 --- /dev/null +++ b/spring-5-reactive-oauth/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-5-reactive-security/pom.xml b/spring-5-reactive-security/pom.xml index 3b64b9b3ac..72a73a86ce 100644 --- a/spring-5-reactive-security/pom.xml +++ b/spring-5-reactive-security/pom.xml @@ -2,12 +2,11 @@ 4.0.0 - com.baeldung spring-5-reactive-security 0.0.1-SNAPSHOT - jar spring-5-reactive-security + jar spring 5 security sample project about new features diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index fc898a56dc..538a15c879 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 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) @@ -17,4 +17,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Guide to Spring Session Reactive Support: WebSession](https://www.baeldung.com/spring-session-reactive) - [Validation for Functional Endpoints in Spring 5](https://www.baeldung.com/spring-functional-endpoints-validation) - [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) diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index 63cc185afe..8d5324a673 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -2,12 +2,11 @@ 4.0.0 - com.baeldung spring-5-reactive 0.0.1-SNAPSHOT - jar spring-5-reactive + jar spring 5 sample project about new features @@ -125,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 0000000000..2fa6c7b8c5 Binary files /dev/null and b/spring-5-reactive/src/main/resources/img/example-image.png differ diff --git a/spring-5-reactive/src/main/resources/public/index.html b/spring-5-reactive/src/main/resources/public/index.html new file mode 100644 index 0000000000..7a3b9413cd --- /dev/null +++ b/spring-5-reactive/src/main/resources/public/index.html @@ -0,0 +1,10 @@ + + + + + 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/reactive/errorhandling/ErrorHandlingIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java index 10cfaffce4..42da90ecd5 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java @@ -1,10 +1,13 @@ package com.baeldung.reactive.errorhandling; -import java.io.IOException; 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.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.http.MediaType; @@ -15,6 +18,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) @WithMockUser +@AutoConfigureWebTestClient(timeout = "10000") public class ErrorHandlingIntegrationTest { @Autowired diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/filters/PlayerHandlerIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/filters/PlayerHandlerIntegrationTest.java index fbf46a93cc..c1523cb5ee 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/filters/PlayerHandlerIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/filters/PlayerHandlerIntegrationTest.java @@ -3,6 +3,7 @@ package com.baeldung.reactive.filters; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit4.SpringRunner; @@ -14,6 +15,7 @@ import static org.junit.Assert.assertEquals; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @WithMockUser +@AutoConfigureWebTestClient(timeout = "10000") public class PlayerHandlerIntegrationTest { @Autowired 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 diff --git a/spring-5-reactive/src/test/java/com/baeldung/stepverifier/PostExecutionUnitTest.java b/spring-5-reactive/src/test/java/com/baeldung/stepverifier/PostExecutionUnitTest.java index 17fea6b50b..4395e0b048 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/stepverifier/PostExecutionUnitTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/stepverifier/PostExecutionUnitTest.java @@ -28,7 +28,7 @@ public class PostExecutionUnitTest { .expectComplete() .verifyThenAssertThat() .hasDropped(4) - .tookLessThan(Duration.ofMillis(1050)); + .tookLessThan(Duration.ofMillis(1500)); } } diff --git a/spring-5-security-cognito/README.md b/spring-5-security-cognito/README.md new file mode 100644 index 0000000000..0825882c05 --- /dev/null +++ b/spring-5-security-cognito/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Authenticating with Amazon Cognito Using Spring Security](https://www.baeldung.com/spring-security-oauth-cognito) diff --git a/spring-5-security-cognito/pom.xml b/spring-5-security-cognito/pom.xml new file mode 100644 index 0000000000..431c9b8d9c --- /dev/null +++ b/spring-5-security-cognito/pom.xml @@ -0,0 +1,73 @@ + + 4.0.0 + com.baeldung + spring-5-security-cognito + 0.0.1-SNAPSHOT + spring-5-security-cognito + jar + spring 5 security oauth cognito sample project + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity5 + + + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + ${oauth-auto.version} + + + org.springframework.security + spring-security-oauth2-client + + + org.springframework.security + spring-security-oauth2-jose + + + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + 2.1.0.RELEASE + 2.1.0.RELEASE + com.baeldung.cognito.SpringCognitoApplication + + + diff --git a/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java new file mode 100644 index 0000000000..6841fa7a65 --- /dev/null +++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java @@ -0,0 +1,16 @@ +package com.baeldung.cognito; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@PropertySource("cognito/application-cognito.yml") +public class CognitoWebConfiguration implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("home"); + } +} diff --git a/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java new file mode 100644 index 0000000000..eebe6d8f45 --- /dev/null +++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.cognito; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource("cognito/application-cognito.yml") +public class SpringCognitoApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringCognitoApplication.class, args); + } +} diff --git a/spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml b/spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml new file mode 100644 index 0000000000..0a28dbccb4 --- /dev/null +++ b/spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml @@ -0,0 +1,15 @@ +spring: + security: + oauth2: + client: + registration: + cognito: + client-id: clientId + client-secret: clientSecret + scope: openid + redirectUriTemplate: "http://localhost:8080/login/oauth2/code/cognito" + clientName: cognito-client-name + provider: + cognito: + issuerUri: https://cognito-idp.{region}.amazonaws.com/{poolId} + usernameAttribute: cognito:username diff --git a/spring-5-security-cognito/src/main/resources/cognito/home.html b/spring-5-security-cognito/src/main/resources/cognito/home.html new file mode 100644 index 0000000000..f0bd9e52a8 --- /dev/null +++ b/spring-5-security-cognito/src/main/resources/cognito/home.html @@ -0,0 +1,32 @@ + + + + + + OAuth2 Cognito Demo + + + + + +
+
+
+

OAuth2 Spring Security Cognito Demo

+ +
+
+ Hello, ! +
+
+ + +
+
+
+ + diff --git a/spring-5-security-cognito/src/main/resources/cognito/style.css b/spring-5-security-cognito/src/main/resources/cognito/style.css new file mode 100644 index 0000000000..45190d6d70 --- /dev/null +++ b/spring-5-security-cognito/src/main/resources/cognito/style.css @@ -0,0 +1,9 @@ +.login { + background-color: #7289da; + color: #fff; +} + +.login:hover { + background-color: #697ec4; + color: #fff; +} diff --git a/spring-5-security-cognito/src/main/resources/logback.xml b/spring-5-security-cognito/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-5-security-cognito/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-5-security-oauth/README.md b/spring-5-security-oauth/README.md index f13925992b..a5cec370c7 100644 --- a/spring-5-security-oauth/README.md +++ b/spring-5-security-oauth/README.md @@ -1,4 +1,5 @@ ## Relevant articles: -- [Spring Security 5 -OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login) +- [Spring Security 5 – OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login) - [Extracting Principal and Authorities using Spring Security OAuth](https://www.baeldung.com/spring-security-oauth-principal-authorities-extractor) +- [Customizing Authorization and Token Requests with Spring Security 5.1 Client](https://www.baeldung.com/spring-security-custom-oauth-requests) diff --git a/spring-5-security-oauth/pom.xml b/spring-5-security-oauth/pom.xml index 59150a153f..d9a1e3094e 100644 --- a/spring-5-security-oauth/pom.xml +++ b/spring-5-security-oauth/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-5-security-oauth 0.0.1-SNAPSHOT - jar spring-5-security-oauth + jar spring 5 security oauth sample project diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java index 557c23b368..1478b03d2e 100644 --- a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java +++ b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java @@ -2,7 +2,9 @@ package com.baeldung.oauth2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; +@PropertySource("classpath:default-application.properties") @SpringBootApplication public class SpringOAuthApplication { diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java index 6ab4d525bf..174e5b0fdf 100644 --- a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java +++ b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java @@ -3,10 +3,12 @@ package com.baeldung.oauth2extractors; import org.apache.logging.log4j.util.Strings; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.AbstractEnvironment; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +@PropertySource("classpath:default-application.properties") @SpringBootApplication @Controller public class ExtractorsApplication { diff --git a/spring-5-security-oauth/src/main/resources/application.properties b/spring-5-security-oauth/src/main/resources/application.properties index 5912b0f755..c84e745918 100644 --- a/spring-5-security-oauth/src/main/resources/application.properties +++ b/spring-5-security-oauth/src/main/resources/application.properties @@ -1,5 +1,3 @@ -server.port=8081 - logging.level.root=INFO logging.level.com.baeldung.dsl.ClientErrorLoggingFilter=DEBUG \ No newline at end of file diff --git a/spring-5-security-oauth/src/main/resources/default-application.properties b/spring-5-security-oauth/src/main/resources/default-application.properties new file mode 100644 index 0000000000..bafddced85 --- /dev/null +++ b/spring-5-security-oauth/src/main/resources/default-application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/spring-5-security/pom.xml b/spring-5-security/pom.xml index c26e370381..413337633f 100644 --- a/spring-5-security/pom.xml +++ b/spring-5-security/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-5-security 0.0.1-SNAPSHOT - jar spring-5-security + jar spring 5 security sample project @@ -16,7 +16,6 @@ - org.springframework.boot spring-boot-starter-security 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 diff --git a/spring-5-webflux/README.md b/spring-5-webflux/README.md new file mode 100644 index 0000000000..87d9ae0dd3 --- /dev/null +++ b/spring-5-webflux/README.md @@ -0,0 +1,6 @@ +## Relevant articles: + +- [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty) +- [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404) +- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters) +- [RSocket Using Spring Boot](https://www.baeldung.com/spring-boot-rsocket) diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml new file mode 100644 index 0000000000..6317723467 --- /dev/null +++ b/spring-5-webflux/pom.xml @@ -0,0 +1,105 @@ + + + + 4.0.0 + com.baeldung + spring-5-webflux + 1.0-SNAPSHOT + spring-5-webflux + http://www.baeldung.com + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.springframework.boot + spring-boot-starter-rsocket + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.projectreactor + reactor-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + 1.8 + 2.2.0.M3 + + 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/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java new file mode 100644 index 0000000000..6f35ec5ee0 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.rsocket.client; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class ClientApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder() + .main(ClientApplication.class) + .sources(ClientApplication.class) + .profiles("client") + .run(args); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java new file mode 100644 index 0000000000..7dd3591cd6 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/ClientConfiguration.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.rsocket.client; + +import io.rsocket.RSocket; +import io.rsocket.RSocketFactory; +import io.rsocket.frame.decoder.PayloadDecoder; +import io.rsocket.transport.netty.client.TcpClientTransport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketStrategies; +import org.springframework.util.MimeTypeUtils; + +@Configuration +public class ClientConfiguration { + + @Bean + public RSocket rSocket() { + return RSocketFactory.connect() + .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE) + .frameDecoder(PayloadDecoder.ZERO_COPY) + .transport(TcpClientTransport.create(7000)) + .start() + .block(); + } + + @Bean + RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) { + return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java new file mode 100644 index 0000000000..3701bd69e9 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/client/MarketDataRestController.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.rsocket.client; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import java.util.Random; +import org.reactivestreams.Publisher; +import org.springframework.http.MediaType; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MarketDataRestController { + + private final Random random = new Random(); + private final RSocketRequester rSocketRequester; + + public MarketDataRestController(RSocketRequester rSocketRequester) { + this.rSocketRequester = rSocketRequester; + } + + @GetMapping(value = "/current/{stock}") + public Publisher current(@PathVariable("stock") String stock) { + return rSocketRequester.route("currentMarketData") + .data(new MarketDataRequest(stock)) + .retrieveMono(MarketData.class); + } + + @GetMapping(value = "/feed/{stock}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Publisher feed(@PathVariable("stock") String stock) { + return rSocketRequester.route("feedMarketData") + .data(new MarketDataRequest(stock)) + .retrieveFlux(MarketData.class); + } + + @GetMapping(value = "/collect") + public Publisher collect() { + return rSocketRequester.route("collectMarketData") + .data(getMarketData()) + .send(); + } + + private MarketData getMarketData() { + return new MarketData("X", random.nextInt(10)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java new file mode 100644 index 0000000000..3eeaf449e9 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketData.java @@ -0,0 +1,20 @@ +package com.baeldung.spring.rsocket.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MarketData { + + private String stock; + private int currentPrice; + + public static MarketData fromException(Exception e) { + MarketData marketData = new MarketData(); + marketData.setStock(e.getMessage()); + return marketData; + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java new file mode 100644 index 0000000000..1debbb0870 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/model/MarketDataRequest.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.rsocket.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MarketDataRequest { + + private String stock; +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java new file mode 100644 index 0000000000..1ff23966fa --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRSocketController.java @@ -0,0 +1,40 @@ +package com.baeldung.spring.rsocket.server; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import org.springframework.messaging.handler.annotation.MessageExceptionHandler; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.stereotype.Controller; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Controller +public class MarketDataRSocketController { + + private final MarketDataRepository marketDataRepository; + + public MarketDataRSocketController(MarketDataRepository marketDataRepository) { + this.marketDataRepository = marketDataRepository; + } + + @MessageMapping("currentMarketData") + public Mono currentMarketData(MarketDataRequest marketDataRequest) { + return marketDataRepository.getOne(marketDataRequest.getStock()); + } + + @MessageMapping("feedMarketData") + public Flux feedMarketData(MarketDataRequest marketDataRequest) { + return marketDataRepository.getAll(marketDataRequest.getStock()); + } + + @MessageMapping("collectMarketData") + public Mono collectMarketData(MarketData marketData) { + marketDataRepository.add(marketData); + return Mono.empty(); + } + + @MessageExceptionHandler + public Mono handleException(Exception e) { + return Mono.just(MarketData.fromException(e)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java new file mode 100644 index 0000000000..4f30c36c2f --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/MarketDataRepository.java @@ -0,0 +1,37 @@ +package com.baeldung.spring.rsocket.server; + +import com.baeldung.spring.rsocket.model.MarketData; +import java.time.Duration; +import java.util.Random; +import java.util.stream.Stream; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Slf4j +@Component +public class MarketDataRepository { + + private static final int BOUND = 100; + + private Random random = new Random(); + + public Flux getAll(String stock) { + return Flux.fromStream(Stream.generate(() -> getMarketDataResponse(stock))) + .log() + .delayElements(Duration.ofSeconds(1)); + } + + public Mono getOne(String stock) { + return Mono.just(getMarketDataResponse(stock)); + } + + public void add(MarketData marketData) { + log.info("New market data: {}", marketData); + } + + private MarketData getMarketDataResponse(String stock) { + return new MarketData(stock, random.nextInt(BOUND)); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java new file mode 100644 index 0000000000..4213e315dd --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/rsocket/server/ServerApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.rsocket.server; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class ServerApplication { + + public static void main(String[] args) { + new SpringApplicationBuilder() + .main(ServerApplication.class) + .sources(ServerApplication.class) + .profiles("server") + .run(args); + } +} 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/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java b/spring-5-webflux/src/main/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java new file mode 100644 index 0000000000..314fe2fdf9 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/webclientrequests/SpringWebClientRequestsApp.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.webclientrequests; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringWebClientRequestsApp { + + public static void main(String[] args) { + SpringApplication.run(SpringWebClientRequestsApp.class, args); + } +} diff --git a/spring-5-webflux/src/main/resources/application-client.properties b/spring-5-webflux/src/main/resources/application-client.properties new file mode 100644 index 0000000000..4c00e40deb --- /dev/null +++ b/spring-5-webflux/src/main/resources/application-client.properties @@ -0,0 +1 @@ +server.port=8080 diff --git a/spring-5-webflux/src/main/resources/application-server.properties b/spring-5-webflux/src/main/resources/application-server.properties new file mode 100644 index 0000000000..1e343b5bf5 --- /dev/null +++ b/spring-5-webflux/src/main/resources/application-server.properties @@ -0,0 +1,2 @@ +spring.rsocket.server.port=7000 +server.port=8081 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 0000000000..6aa9a28053 Binary files /dev/null and b/spring-5-webflux/src/main/resources/sample.jks differ diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.java new file mode 100644 index 0000000000..4c6708e423 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.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 ResponseStatusControllerLiveTest { + + @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(); + } +} diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java new file mode 100644 index 0000000000..ff00d5ec24 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/client/MarketDataRestControllerIntegrationTest.java @@ -0,0 +1,92 @@ +package com.baeldung.spring.rsocket.client; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.http.MediaType.TEXT_EVENT_STREAM; + +import com.baeldung.spring.rsocket.model.MarketData; +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.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketRequester.RequestSpec; +import org.springframework.messaging.rsocket.RSocketRequester.ResponseSpec; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.FluxExchangeResult; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +@RunWith(SpringRunner.class) +@WebFluxTest(value = MarketDataRestController.class) +public class MarketDataRestControllerIntegrationTest { + + @Autowired + private WebTestClient testClient; + + @MockBean + private RSocketRequester rSocketRequester; + + @Mock + private RequestSpec requestSpec; + + @Mock + private ResponseSpec responseSpec; + + @Test + public void whenInitiatesRequest_ThenGetsResponse() throws Exception { + when(rSocketRequester.route("currentMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + MarketData marketData = new MarketData("X", 1); + when(responseSpec.retrieveMono(MarketData.class)).thenReturn(Mono.just(marketData)); + + testClient.get() + .uri("/current/{stock}", "X") + .exchange() + .expectStatus() + .isOk() + .expectBody(MarketData.class) + .isEqualTo(marketData); + } + + @Test + public void whenInitiatesFireAndForget_ThenGetsNoResponse() throws Exception { + when(rSocketRequester.route("collectMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + when(responseSpec.send()).thenReturn(Mono.empty()); + + testClient.get() + .uri("/collect") + .exchange() + .expectStatus() + .isOk() + .expectBody(Void.class); + } + + @Test + public void whenInitiatesRequest_ThenGetsStream() throws Exception { + when(rSocketRequester.route("feedMarketData")).thenReturn(requestSpec); + when(requestSpec.data(any())).thenReturn(responseSpec); + MarketData firstMarketData = new MarketData("X", 1); + MarketData secondMarketData = new MarketData("X", 2); + when(responseSpec.retrieveFlux(MarketData.class)).thenReturn(Flux.just(firstMarketData, secondMarketData)); + + FluxExchangeResult result = testClient.get() + .uri("/feed/{stock}", "X") + .accept(TEXT_EVENT_STREAM) + .exchange() + .expectStatus() + .isOk() + .returnResult(MarketData.class); + Flux marketDataFlux = result.getResponseBody(); + StepVerifier.create(marketDataFlux) + .expectNext(firstMarketData) + .expectNext(secondMarketData) + .thenCancel() + .verify(); + } +} \ No newline at end of file diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java new file mode 100644 index 0000000000..dcf3b82730 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/rsocket/server/MarketDataRSocketControllerLiveTest.java @@ -0,0 +1,98 @@ +package com.baeldung.spring.rsocket.server; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import com.baeldung.spring.rsocket.model.MarketData; +import com.baeldung.spring.rsocket.model.MarketDataRequest; +import io.rsocket.RSocket; +import io.rsocket.RSocketFactory; +import io.rsocket.frame.decoder.PayloadDecoder; +import io.rsocket.transport.netty.client.TcpClientTransport; +import java.time.Duration; +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.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; +import org.springframework.messaging.rsocket.RSocketRequester; +import org.springframework.messaging.rsocket.RSocketStrategies; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.MimeTypeUtils; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(properties = {"spring.rsocket.server.port=7000"}) +public class MarketDataRSocketControllerLiveTest { + + @Autowired + private RSocketRequester rSocketRequester; + + @SpyBean + private MarketDataRSocketController rSocketController; + + @Test + public void whenGetsFireAndForget_ThenReturnsNoResponse() throws InterruptedException { + final MarketData marketData = new MarketData("X", 1); + rSocketRequester.route("collectMarketData") + .data(marketData) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).collectMarketData(any()); + } + + @Test + public void whenGetsRequest_ThenReturnsResponse() throws InterruptedException { + final MarketDataRequest marketDataRequest = new MarketDataRequest("X"); + rSocketRequester.route("currentMarketData") + .data(marketDataRequest) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).currentMarketData(any()); + } + + @Test + public void whenGetsRequest_ThenReturnsStream() throws InterruptedException { + final MarketDataRequest marketDataRequest = new MarketDataRequest("X"); + rSocketRequester.route("feedMarketData") + .data(marketDataRequest) + .send() + .block(Duration.ofSeconds(10)); + + sleepForProcessing(); + verify(rSocketController).feedMarketData(any()); + } + + private void sleepForProcessing() throws InterruptedException { + Thread.sleep(1000); + } + + @TestConfiguration + public static class ClientConfiguration { + + @Bean + @Lazy + public RSocket rSocket() { + return RSocketFactory.connect() + .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE) + .frameDecoder(PayloadDecoder.ZERO_COPY) + .transport(TcpClientTransport.create(7000)) + .start() + .block(); + } + + @Bean + @Lazy + RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) { + return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies); + } + } +} \ No newline at end of file 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/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java new file mode 100644 index 0000000000..353cb24d0a --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/webclientrequests/WebClientRequestsUnitTest.java @@ -0,0 +1,176 @@ +package com.baeldung.spring.webclientrequests; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.time.Duration; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFunction; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.DefaultUriBuilderFactory; +import reactor.core.publisher.Mono; + +@RunWith(SpringRunner.class) +@WebFluxTest +public class WebClientRequestsUnitTest { + + private static final String BASE_URL = "https://example.com"; + + private WebClient webClient; + + @Captor + private ArgumentCaptor argumentCaptor; + + private ExchangeFunction exchangeFunction; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + this.exchangeFunction = mock(ExchangeFunction.class); + ClientResponse mockResponse = mock(ClientResponse.class); + when(this.exchangeFunction.exchange(this.argumentCaptor.capture())).thenReturn(Mono.just(mockResponse)); + this.webClient = WebClient + .builder() + .baseUrl(BASE_URL) + .exchangeFunction(exchangeFunction) + .build(); + } + + + @Test + public void whenCallSimpleURI_thenURIMatched() { + this.webClient.get() + .uri("/products") + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products"); + } + + @Test + public void whenCallSinglePathSegmentUri_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/{id}") + .build(2)) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/2"); + } + + @Test + public void whenCallMultiplePathSegmentsUri_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/{id}/attributes/{attributeId}") + .build(2, 13)) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/2/attributes/13"); + } + + @Test + public void whenCallSingleQueryParams_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("name", "AndroidPhone") + .queryParam("color", "black") + .queryParam("deliveryDate", "13/04/2019") + .build()) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13/04/2019"); + } + + @Test + public void whenCallSingleQueryParamsPlaceholders_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("name", "{title}") + .queryParam("color", "{authorId}") + .queryParam("deliveryDate", "{date}") + .build("AndroidPhone", "black", "13/04/2019")) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13%2F04%2F2019"); + } + + @Test + public void whenCallArrayQueryParamsBrackets_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("tag[]", "Snapdragon", "NFC") + .build()) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?tag%5B%5D=Snapdragon&tag%5B%5D=NFC"); + } + + + @Test + public void whenCallArrayQueryParams_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("category", "Phones", "Tablets") + .build()) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?category=Phones&category=Tablets"); + } + + @Test + public void whenCallArrayQueryParamsComma_thenURIMatched() { + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("category", String.join(",", "Phones", "Tablets")) + .build()) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?category=Phones,Tablets"); + } + + @Test + public void whenUriComponentEncoding_thenQueryParamsNotEscaped() { + DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); + factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT); + this.webClient = WebClient + .builder() + .uriBuilderFactory(factory) + .baseUrl(BASE_URL) + .exchangeFunction(exchangeFunction) + .build(); + this.webClient.get() + .uri(uriBuilder -> uriBuilder + .path("/products/") + .queryParam("name", "AndroidPhone") + .queryParam("color", "black") + .queryParam("deliveryDate", "13/04/2019") + .build()) + .exchange() + .block(Duration.ofSeconds(1)); + verifyCalledUrl("/products/?name=AndroidPhone&color=black&deliveryDate=13/04/2019"); + } + + private void verifyCalledUrl(String relativeUrl) { + ClientRequest request = this.argumentCaptor.getValue(); + Assert.assertEquals(String.format("%s%s", BASE_URL, relativeUrl), request.url().toString()); + Mockito.verify(this.exchangeFunction).exchange(request); + verifyNoMoreInteractions(this.exchangeFunction); + } +} 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 + + + + + + + diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 58c14475e0..6e4162fbcc 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -6,8 +6,8 @@ com.baeldung spring-5 0.0.1-SNAPSHOT - jar spring-5 + jar spring 5 sample project about new features @@ -156,7 +156,6 @@ 4.1 ${project.build.directory}/generated-snippets 2.21.0 -
diff --git a/spring-5/src/main/java/com/baeldung/components/AccountService.java b/spring-5/src/main/java/com/baeldung/components/AccountService.java new file mode 100644 index 0000000000..c2f09c735e --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/components/AccountService.java @@ -0,0 +1,8 @@ +package com.baeldung.components; + +import org.springframework.stereotype.Component; + +@Component +public class AccountService { + +} diff --git a/spring-5/src/main/java/com/baeldung/components/UserService.java b/spring-5/src/main/java/com/baeldung/components/UserService.java new file mode 100644 index 0000000000..80e5e0c632 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/components/UserService.java @@ -0,0 +1,16 @@ +package com.baeldung.components; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class UserService { + + @Autowired + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + +} diff --git a/spring-5/src/main/resources/beans.xml b/spring-5/src/main/resources/beans.xml new file mode 100644 index 0000000000..004745b817 --- /dev/null +++ b/spring-5/src/main/resources/beans.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/SpringXMLConfigurationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/SpringXMLConfigurationIntegrationTest.java new file mode 100644 index 0000000000..4ecad9c43e --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/SpringXMLConfigurationIntegrationTest.java @@ -0,0 +1,23 @@ +package com.baeldung; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import com.baeldung.components.AccountService; +import com.baeldung.components.UserService; + +public class SpringXMLConfigurationIntegrationTest { + + @Test + public void givenContextAnnotationConfigOrContextComponentScan_whenDependenciesAndBeansAnnotated_thenNoXMLNeeded() { + ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml"); + UserService userService = context.getBean(UserService.class); + AccountService accountService = context.getBean(AccountService.class); + Assert.assertNotNull(userService); + Assert.assertNotNull(accountService); + Assert.assertNotNull(userService.getAccountService()); + } + +} diff --git a/spring-activiti/pom.xml b/spring-activiti/pom.xml index 4e21c5b032..e0196e807d 100644 --- a/spring-activiti/pom.xml +++ b/spring-activiti/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-activiti - jar spring-activiti + jar Demo project for Spring Boot @@ -59,7 +59,6 @@ UTF-8 UTF-8 6.0.0 - 1.8
diff --git a/spring-activiti/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-activiti/src/test/java/com/baeldung/SpringContextIntegrationTest.java index ce48080753..89411df976 100644 --- a/spring-activiti/src/test/java/com/baeldung/SpringContextIntegrationTest.java +++ b/spring-activiti/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -2,6 +2,7 @@ package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @@ -9,6 +10,7 @@ import com.baeldung.activitiwithspring.ActivitiWithSpringApplication; @RunWith(SpringRunner.class) @SpringBootTest(classes = ActivitiWithSpringApplication.class) +@AutoConfigureTestDatabase public class SpringContextIntegrationTest { @Test diff --git a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java index 53bdcee888..7f99483fcf 100644 --- a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java +++ b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java @@ -4,6 +4,7 @@ import org.activiti.engine.IdentityService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.test.context.junit4.SpringRunner; @@ -14,6 +15,7 @@ import com.baeldung.activiti.security.withspring.ActivitiSpringSecurityApplicati @RunWith(SpringRunner.class) @SpringBootTest(classes = ActivitiSpringSecurityApplication.class) @WebAppConfiguration +@AutoConfigureTestDatabase public class ActivitiSpringSecurityIntegrationTest { @Autowired private IdentityService identityService; diff --git a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiWithSpringApplicationIntegrationTest.java b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiWithSpringApplicationIntegrationTest.java index 8c1e400215..d289693a73 100644 --- a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiWithSpringApplicationIntegrationTest.java +++ b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ActivitiWithSpringApplicationIntegrationTest.java @@ -2,11 +2,13 @@ package com.baeldung.activitiwithspring; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) -@SpringBootTest +@SpringBootTest(classes = ActivitiWithSpringApplication.class) +@AutoConfigureTestDatabase public class ActivitiWithSpringApplicationIntegrationTest { @Test diff --git a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ProcessEngineCreationIntegrationTest.java b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ProcessEngineCreationIntegrationTest.java index 00538f8e6e..5052f84d6a 100644 --- a/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ProcessEngineCreationIntegrationTest.java +++ b/spring-activiti/src/test/java/com/baeldung/activitiwithspring/ProcessEngineCreationIntegrationTest.java @@ -4,7 +4,7 @@ import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.ProcessEngines; import org.junit.Test; - +import org.junit.After; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -62,4 +62,9 @@ public class ProcessEngineCreationIntegrationTest { assertNotNull(processEngine); assertEquals("sa", processEngine.getProcessEngineConfiguration().getJdbcUsername()); } + + @After + public void cleanup() { + ProcessEngines.destroy(); + } } diff --git a/spring-akka/pom.xml b/spring-akka/pom.xml index 92b3f1162d..d8b943b5ae 100644 --- a/spring-akka/pom.xml +++ b/spring-akka/pom.xml @@ -19,7 +19,7 @@ com.typesafe.akka - akka-actor_2.11 + akka-actor_${scala.version} ${akka.version} @@ -44,6 +44,7 @@ 4.3.4.RELEASE 2.4.14 + 2.11 \ No newline at end of file diff --git a/spring-all/README.md b/spring-all/README.md index 0d78efdcf2..b5e91d8d60 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -11,26 +11,26 @@ 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) -- [Guide To Running Logic on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) +- [What’s New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) +- [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) - [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) - [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) - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) +- [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) diff --git a/spring-all/pom.xml b/spring-all/pom.xml index 77c7e74e08..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 @@ -160,12 +164,12 @@ net.javacrumbs.shedlock shedlock-spring - 2.1.0 + ${shedlock.version} net.javacrumbs.shedlock shedlock-provider-jdbc-template - 2.1.0 + ${shedlock.version} @@ -227,13 +231,13 @@ - + org.baeldung.sample.App 5.0.6.RELEASE 1.2.0.RELEASE - + 1.3.2 5.2.5.Final @@ -243,7 +247,7 @@ 3.6 3.6.1 6.6.0 - + 2.1.0 3.22.0-GA diff --git a/spring-all/src/main/java/org/baeldung/primary/Config.java b/spring-all/src/main/java/org/baeldung/primary/Config.java index b39f2b9db3..bdcfe019e6 100644 --- a/spring-all/src/main/java/org/baeldung/primary/Config.java +++ b/spring-all/src/main/java/org/baeldung/primary/Config.java @@ -10,13 +10,13 @@ import org.springframework.context.annotation.Primary; public class Config { @Bean - public Employee JohnEmployee(){ + public Employee johnEmployee(){ return new Employee("John"); } @Bean @Primary - public Employee TonyEmployee(){ + public Employee tonyEmployee(){ return new Employee("Tony"); } } 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/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/BasketballService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/BasketballService.java new file mode 100644 index 0000000000..c117231d3c --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/BasketballService.java @@ -0,0 +1,13 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class BasketballService extends BallService { + + @Autowired + 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 new file mode 100644 index 0000000000..615d354ecf --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java @@ -0,0 +1,18 @@ +package org.baeldung.sampleabstract; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = "org.baeldung.sampleabstract") +public class DemoApp { + + + public static void main(String[] args) { + + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoApp.class); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java b/spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java new file mode 100644 index 0000000000..3a65671493 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class LogRepository { + + @Override + public String toString() { + return "logRepository"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java b/spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java new file mode 100644 index 0000000000..fd42178ab6 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class RuleRepository { + + @Override + public String toString() { + return "ruleRepository"; + } +} 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"); + } +} diff --git a/spring-amqp-simple/pom.xml b/spring-amqp-simple/pom.xml index 57d84acee6..45cdc066a0 100644 --- a/spring-amqp-simple/pom.xml +++ b/spring-amqp-simple/pom.xml @@ -8,10 +8,10 @@ spring-amqp-simple - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java index f6c82b635e..92fa28ed6f 100644 --- a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java +++ b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java @@ -35,7 +35,7 @@ public class SpringAmqpConfig { } @Bean - SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, + SimpleMessageListenerContainer springAmqpContainer(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); container.setConnectionFactory(connectionFactory); diff --git a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java index 1d02b4dad9..868cfff0ac 100644 --- a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java +++ b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java @@ -61,7 +61,7 @@ public class BroadcastConfig { } @Bean - public SimpleRabbitListenerContainerFactory container(ConnectionFactory connectionFactory, SimpleRabbitListenerContainerFactoryConfigurer configurer) { + public SimpleRabbitListenerContainerFactory broadcastContainer(ConnectionFactory connectionFactory, SimpleRabbitListenerContainerFactoryConfigurer configurer) { SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); configurer.configure(factory, connectionFactory); return factory; diff --git a/spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java similarity index 90% rename from spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java index f134074cf8..03cb34eeb5 100644 --- a/spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java @@ -9,7 +9,7 @@ import com.baeldung.springamqpsimple.SpringAmqpApplication; @RunWith(SpringRunner.class) @SpringBootTest(classes = SpringAmqpApplication.class) -public class SpringContextIntegrationTest { +public class SpringContextManualTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/spring-amqp-simple/src/test/resources/application.yaml b/spring-amqp-simple/src/test/resources/application.yaml new file mode 100644 index 0000000000..aa7a91bac5 --- /dev/null +++ b/spring-amqp-simple/src/test/resources/application.yaml @@ -0,0 +1,5 @@ +spring: + rabbitmq: + username: guest + password: guest + host: localhost \ No newline at end of file diff --git a/spring-amqp/pom.xml b/spring-amqp/pom.xml index e08a4243b3..c021bd49ff 100755 --- a/spring-amqp/pom.xml +++ b/spring-amqp/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-amqp 0.1-SNAPSHOT - jar spring-amqp + jar Introduction to Spring-AMQP diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml index 368f3ada14..a1e2ffd534 100644 --- a/spring-aop/pom.xml +++ b/spring-aop/pom.xml @@ -2,14 +2,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-aop - war spring-aop + war - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/spring-apache-camel/.gitignore b/spring-apache-camel/.gitignore new file mode 100644 index 0000000000..eac473ac50 --- /dev/null +++ b/spring-apache-camel/.gitignore @@ -0,0 +1 @@ +/src/test/destination-folder/* \ No newline at end of file diff --git a/spring-apache-camel/pom.xml b/spring-apache-camel/pom.xml index 662b3f899c..3e76c0c7f1 100644 --- a/spring-apache-camel/pom.xml +++ b/spring-apache-camel/pom.xml @@ -3,9 +3,9 @@ 4.0.0 org.apache.camel spring-apache-camel - jar 1.0-SNAPSHOT spring-apache-camel + jar http://maven.apache.org diff --git a/spring-batch/.gitignore b/spring-batch/.gitignore new file mode 100644 index 0000000000..0ef6d10b38 --- /dev/null +++ b/spring-batch/.gitignore @@ -0,0 +1 @@ +output.csv \ No newline at end of file diff --git a/spring-batch/README.md b/spring-batch/README.md index 737e7e13f5..ddd830cd47 100644 --- a/spring-batch/README.md +++ b/spring-batch/README.md @@ -6,5 +6,5 @@ ### Relevant Articles: - [Introduction to Spring Batch](http://www.baeldung.com/introduction-to-spring-batch) - [Spring Batch using Partitioner](http://www.baeldung.com/spring-batch-partitioner) -- [Spring Batch Tasklets vs Chunks Approach](http://www.baeldung.com/spring-batch-tasklet-chunk) +- [Spring Batch – Tasklets vs Chunks](http://www.baeldung.com/spring-batch-tasklet-chunk) - [How to Trigger and Stop a Scheduled Spring Batch Job](http://www.baeldung.com/spring-batch-start-stop-job) diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index cfd725b2bd..e81078568b 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-batch 0.1-SNAPSHOT - jar spring-batch + jar http://maven.apache.org diff --git a/spring-batch/src/main/java/org/baeldung/batch/App.java b/spring-batch/src/main/java/org/baeldung/batch/App.java index cea4e8d486..8bf58e65d2 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/App.java +++ b/spring-batch/src/main/java/org/baeldung/batch/App.java @@ -3,6 +3,7 @@ package org.baeldung.batch; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -21,7 +22,11 @@ public class App { final Job job = (Job) context.getBean("firstBatchJob"); System.out.println("Starting the batch job"); try { - final JobExecution execution = jobLauncher.run(job, new JobParameters()); + // To enable multiple execution of a job with the same parameters + JobParameters jobParameters = new JobParametersBuilder() + .addString("jobID", String.valueOf(System.currentTimeMillis())) + .toJobParameters(); + final JobExecution execution = jobLauncher.run(job, jobParameters); System.out.println("Job Status : " + execution.getStatus()); System.out.println("Job succeeded"); } catch (final Exception e) { diff --git a/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-admin/spring-boot-admin-client/pom.xml index ea03d6ef6d..7563a01172 100644 --- a/spring-boot-admin/spring-boot-admin-client/pom.xml +++ b/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -4,9 +4,9 @@ 4.0.0 spring-boot-admin-client 0.0.1-SNAPSHOT - jar spring-boot-admin-client Spring Boot Admin Client + jar spring-boot-admin diff --git a/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-admin/spring-boot-admin-server/pom.xml index d8e7bb5574..d429d9289f 100644 --- a/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -4,9 +4,9 @@ 4.0.0 spring-boot-admin-server 0.0.1-SNAPSHOT - jar spring-boot-admin-server Spring Boot Admin Server + jar spring-boot-admin diff --git a/spring-boot-angular-ecommerce/pom.xml b/spring-boot-angular-ecommerce/pom.xml index dc92a91d02..510e6c6ec3 100644 --- a/spring-boot-angular-ecommerce/pom.xml +++ b/spring-boot-angular-ecommerce/pom.xml @@ -2,12 +2,10 @@ 4.0.0 - spring-boot-angular-ecommerce 0.0.1-SNAPSHOT - jar - spring-boot-angular-ecommerce + jar Spring Boot Angular E-commerce Appliciation @@ -77,7 +75,6 @@ UTF-8 UTF-8 - 1.8 2.0.3.RELEASE 2.0.4.RELEASE 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" 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) + diff --git a/spring-boot-angular/angularclient/.angular-cli.json b/spring-boot-angular/angularclient/.angular-cli.json new file mode 100644 index 0000000000..3de2a62f41 --- /dev/null +++ b/spring-boot-angular/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/angularclient/.editorconfig b/spring-boot-angular/angularclient/.editorconfig new file mode 100644 index 0000000000..6e87a003da --- /dev/null +++ b/spring-boot-angular/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/angularclient/.gitignore b/spring-boot-angular/angularclient/.gitignore new file mode 100644 index 0000000000..eabf65e51a --- /dev/null +++ b/spring-boot-angular/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/angularclient/README.md b/spring-boot-angular/angularclient/README.md new file mode 100644 index 0000000000..6fec59bc13 --- /dev/null +++ b/spring-boot-angular/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/angularclient/e2e/app.e2e-spec.ts b/spring-boot-angular/angularclient/e2e/app.e2e-spec.ts new file mode 100644 index 0000000000..d72f8a4e91 --- /dev/null +++ b/spring-boot-angular/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/angularclient/e2e/app.po.ts b/spring-boot-angular/angularclient/e2e/app.po.ts new file mode 100644 index 0000000000..82ea75ba50 --- /dev/null +++ b/spring-boot-angular/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/angularclient/e2e/tsconfig.e2e.json b/spring-boot-angular/angularclient/e2e/tsconfig.e2e.json new file mode 100644 index 0000000000..1d9e5edf09 --- /dev/null +++ b/spring-boot-angular/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/angularclient/karma.conf.js b/spring-boot-angular/angularclient/karma.conf.js new file mode 100644 index 0000000000..af139fada3 --- /dev/null +++ b/spring-boot-angular/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/angularclient/package-lock.json b/spring-boot-angular/angularclient/package-lock.json new file mode 100644 index 0000000000..9ddc0a9ae0 --- /dev/null +++ b/spring-boot-angular/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/angularclient/package.json b/spring-boot-angular/angularclient/package.json new file mode 100644 index 0000000000..a745cf671a --- /dev/null +++ b/spring-boot-angular/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/angularclient/protractor.conf.js b/spring-boot-angular/angularclient/protractor.conf.js new file mode 100644 index 0000000000..7ee3b5ee86 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/app-routing.module.ts b/spring-boot-angular/angularclient/src/app/app-routing.module.ts new file mode 100644 index 0000000000..ecc848ac37 --- /dev/null +++ b/spring-boot-angular/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-apache-camel/src/test/destination-folder/2016-12-18 22-00-11File1.txt b/spring-boot-angular/angularclient/src/app/app.component.css similarity index 100% rename from spring-apache-camel/src/test/destination-folder/2016-12-18 22-00-11File1.txt rename to spring-boot-angular/angularclient/src/app/app.component.css diff --git a/spring-boot-angular/angularclient/src/app/app.component.html b/spring-boot-angular/angularclient/src/app/app.component.html new file mode 100644 index 0000000000..144a77ffe3 --- /dev/null +++ b/spring-boot-angular/angularclient/src/app/app.component.html @@ -0,0 +1,16 @@ +
+
+
+
+
+

{{ title }}

+ +
+
+ +
+
+
\ No newline at end of file diff --git a/spring-boot-angular/angularclient/src/app/app.component.spec.ts b/spring-boot-angular/angularclient/src/app/app.component.spec.ts new file mode 100644 index 0000000000..e4ca195309 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/app.component.ts b/spring-boot-angular/angularclient/src/app/app.component.ts new file mode 100644 index 0000000000..b14112f90b --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/app.module.ts b/spring-boot-angular/angularclient/src/app/app.module.ts new file mode 100644 index 0000000000..3c6c070d96 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/model/user.ts b/spring-boot-angular/angularclient/src/app/model/user.ts new file mode 100644 index 0000000000..f78cda4bf9 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/service/user.service.spec.ts b/spring-boot-angular/angularclient/src/app/service/user.service.spec.ts new file mode 100644 index 0000000000..b26195c25d --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/service/user.service.ts b/spring-boot-angular/angularclient/src/app/service/user.service.ts new file mode 100644 index 0000000000..e587632017 --- /dev/null +++ b/spring-boot-angular/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-apache-camel/src/test/destination-folder/2016-12-18 22-00-11File2.txt b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.css similarity index 100% rename from spring-apache-camel/src/test/destination-folder/2016-12-18 22-00-11File2.txt rename to spring-boot-angular/angularclient/src/app/user-form/user-form.component.css diff --git a/spring-boot-angular/angularclient/src/app/user-form/user-form.component.html b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.html new file mode 100644 index 0000000000..7cf1800e50 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/user-form/user-form.component.spec.ts b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.spec.ts new file mode 100644 index 0000000000..9e613476f5 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/user-form/user-form.component.ts b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.ts new file mode 100644 index 0000000000..869d53aede --- /dev/null +++ b/spring-boot-angular/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-cloud/spring-cloud-aws/.attach_pid23938 b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.css similarity index 100% rename from spring-cloud/spring-cloud-aws/.attach_pid23938 rename to spring-boot-angular/angularclient/src/app/user-list/user-list.component.css diff --git a/spring-boot-angular/angularclient/src/app/user-list/user-list.component.html b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.html new file mode 100644 index 0000000000..1ac849f552 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/user-list/user-list.component.spec.ts b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.spec.ts new file mode 100644 index 0000000000..9d521807d6 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/app/user-list/user-list.component.ts b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.ts new file mode 100644 index 0000000000..91226695f5 --- /dev/null +++ b/spring-boot-angular/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-cloud/spring-cloud-security/auth-client/src/main/resources/application.properties b/spring-boot-angular/angularclient/src/assets/.gitkeep similarity index 100% rename from spring-cloud/spring-cloud-security/auth-client/src/main/resources/application.properties rename to spring-boot-angular/angularclient/src/assets/.gitkeep diff --git a/spring-boot-angular/angularclient/src/environments/environment.prod.ts b/spring-boot-angular/angularclient/src/environments/environment.prod.ts new file mode 100644 index 0000000000..3612073bc3 --- /dev/null +++ b/spring-boot-angular/angularclient/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/spring-boot-angular/angularclient/src/environments/environment.ts b/spring-boot-angular/angularclient/src/environments/environment.ts new file mode 100644 index 0000000000..b7f639aeca --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/favicon.ico b/spring-boot-angular/angularclient/src/favicon.ico new file mode 100644 index 0000000000..8081c7ceaf Binary files /dev/null and b/spring-boot-angular/angularclient/src/favicon.ico differ diff --git a/spring-boot-angular/angularclient/src/index.html b/spring-boot-angular/angularclient/src/index.html new file mode 100644 index 0000000000..1ce7ff1ca6 --- /dev/null +++ b/spring-boot-angular/angularclient/src/index.html @@ -0,0 +1,17 @@ + + + + + + Spring Boot - Angular Application + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-angular/angularclient/src/main.ts b/spring-boot-angular/angularclient/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/polyfills.ts b/spring-boot-angular/angularclient/src/polyfills.ts new file mode 100644 index 0000000000..af84770782 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/styles.css b/spring-boot-angular/angularclient/src/styles.css new file mode 100644 index 0000000000..90d4ee0072 --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/tsconfig.app.json b/spring-boot-angular/angularclient/src/tsconfig.app.json new file mode 100644 index 0000000000..39ba8dbacb --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/tsconfig.spec.json b/spring-boot-angular/angularclient/src/tsconfig.spec.json new file mode 100644 index 0000000000..ac22a298ac --- /dev/null +++ b/spring-boot-angular/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/angularclient/src/typings.d.ts b/spring-boot-angular/angularclient/src/typings.d.ts new file mode 100644 index 0000000000..ef5c7bd620 --- /dev/null +++ b/spring-boot-angular/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/angularclient/tsconfig.json b/spring-boot-angular/angularclient/tsconfig.json new file mode 100644 index 0000000000..a6c016bf38 --- /dev/null +++ b/spring-boot-angular/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/angularclient/tslint.json b/spring-boot-angular/angularclient/tslint.json new file mode 100644 index 0000000000..9963d6c395 --- /dev/null +++ b/spring-boot-angular/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/pom.xml b/spring-boot-angular/pom.xml new file mode 100644 index 0000000000..62a2701dd0 --- /dev/null +++ b/spring-boot-angular/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + com.baeldung.springbootangular + spring-boot-angular + spring-boot-angular + 1.0 + jar + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + 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 + + + + + + 1.8 + + 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..14c90d5b10 --- /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.baeldung.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..5a81cadcbe --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java @@ -0,0 +1,9 @@ +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 +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..ac86f932b4 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/pom.xml @@ -0,0 +1,50 @@ + + + 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 + + + + + + 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 + + + + + + 1.8 + + \ No newline at end of file diff --git a/spring-boot-autoconfiguration/README.MD b/spring-boot-autoconfiguration/README.MD index a71af54dff..dc9cad539a 100644 --- a/spring-boot-autoconfiguration/README.MD +++ b/spring-boot-autoconfiguration/README.MD @@ -3,4 +3,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Create a Custom Auto-Configuration with Spring Boot](http://www.baeldung.com/spring-boot-custom-auto-configuration) \ No newline at end of file +- [Create a Custom Auto-Configuration with Spring Boot](http://www.baeldung.com/spring-boot-custom-auto-configuration) +- [Guide to ApplicationContextRunner in Spring Boot](https://www.baeldung.com/spring-boot-context-runner) diff --git a/spring-boot-autoconfiguration/pom.xml b/spring-boot-autoconfiguration/pom.xml index 1c3d8796ed..91692ebfff 100644 --- a/spring-boot-autoconfiguration/pom.xml +++ b/spring-boot-autoconfiguration/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-boot-autoconfiguration 0.0.1-SNAPSHOT - war spring-boot-autoconfiguration + war This is simple boot application demonstrating a custom auto-configuration diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java new file mode 100644 index 0000000000..634e49fed3 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/CustomService.java @@ -0,0 +1,10 @@ +package com.baeldung.autoconfiguration.service; + +public class CustomService implements SimpleService { + + @Override + public String serve() { + return "Custom Service"; + } + +} diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java new file mode 100644 index 0000000000..ee91bcb051 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/DefaultService.java @@ -0,0 +1,10 @@ +package com.baeldung.autoconfiguration.service; + +public class DefaultService implements SimpleService { + + @Override + public String serve() { + return "Default Service"; + } + +} diff --git a/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java new file mode 100644 index 0000000000..b6c72d7159 --- /dev/null +++ b/spring-boot-autoconfiguration/src/main/java/com/baeldung/autoconfiguration/service/SimpleService.java @@ -0,0 +1,7 @@ +package com.baeldung.autoconfiguration.service; + +public interface SimpleService { + + public String serve(); + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java new file mode 100644 index 0000000000..494013d1d9 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextLiveTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.autoconfiguration.MySQLAutoconfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MySQLAutoconfiguration.class) +@WebAppConfiguration +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} \ No newline at end of file diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java new file mode 100644 index 0000000000..32f63edde4 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnBeanIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +public class ConditionalOnBeanIntegrationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenDependentBeanIsPresent_thenConditionalBeanCreated() { + this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("created"); + assertThat(context).getBean("created") + .isEqualTo("This is always created"); + assertThat(context).hasBean("createOnBean"); + assertThat(context).getBean("createOnBean") + .isEqualTo("This is created when bean (name=created) is present"); + }); + } + + @Test + public void whenDependentBeanIsPresent_thenConditionalMissingBeanIgnored() { + this.contextRunner.withUserConfiguration(BasicConfiguration.class, ConditionalOnMissingBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("created"); + assertThat(context).getBean("created") + .isEqualTo("This is always created"); + assertThat(context).doesNotHaveBean("createOnMissingBean"); + }); + } + + @Test + public void whenDependentBeanIsNotPresent_thenConditionalMissingBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingBeanConfiguration.class) + .run((context) -> { + assertThat(context).hasBean("createOnMissingBean"); + assertThat(context).getBean("createOnMissingBean") + .isEqualTo("This is created when bean (name=created) is missing"); + assertThat(context).doesNotHaveBean("created"); + }); + } + + @Configuration + protected static class BasicConfiguration { + @Bean + public String created() { + return "This is always created"; + } + } + + @Configuration + @ConditionalOnBean(name = "created") + protected static class ConditionalOnBeanConfiguration { + @Bean + public String createOnBean() { + return "This is created when bean (name=created) is present"; + } + } + + @Configuration + @ConditionalOnMissingBean(name = "created") + protected static class ConditionalOnMissingBeanConfiguration { + @Bean + public String createOnMissingBean() { + return "This is created when bean (name=created) is missing"; + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java new file mode 100644 index 0000000000..f2866867f2 --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnClassIntegrationTest.java @@ -0,0 +1,76 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +public class ConditionalOnClassIntegrationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenDependentClassIsPresent_thenBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) + .run(context -> { + assertThat(context).hasBean("created"); + assertThat(context.getBean("created")).isEqualTo("This is created when ConditionalOnClassIntegrationTest is present on the classpath"); + }); + } + + @Test + public void whenDependentClassIsPresent_thenBeanMissing() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) + .run(context -> { + assertThat(context).doesNotHaveBean("missed"); + }); + } + + @Test + public void whenDependentClassIsNotPresent_thenBeanMissing() { + this.contextRunner.withUserConfiguration(ConditionalOnClassConfiguration.class) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) + .run((context) -> { + assertThat(context).doesNotHaveBean("created"); + assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); + + }); + } + + @Test + public void whenDependentClassIsNotPresent_thenBeanCreated() { + this.contextRunner.withUserConfiguration(ConditionalOnMissingClassConfiguration.class) + .withClassLoader(new FilteredClassLoader(ConditionalOnClassIntegrationTest.class)) + .run((context) -> { + assertThat(context).hasBean("missed"); + assertThat(context).getBean("missed") + .isEqualTo("This is missed when ConditionalOnClassIntegrationTest is present on the classpath"); + assertThat(context).doesNotHaveBean(ConditionalOnClassIntegrationTest.class); + + }); + } + + @Configuration + @ConditionalOnClass(ConditionalOnClassIntegrationTest.class) + protected static class ConditionalOnClassConfiguration { + @Bean + public String created() { + return "This is created when ConditionalOnClassIntegrationTest is present on the classpath"; + } + } + + @Configuration + @ConditionalOnMissingClass("com.baeldung.autoconfiguration.ConditionalOnClassIntegrationTest") + protected static class ConditionalOnMissingClassConfiguration { + @Bean + public String missed() { + return "This is missed when ConditionalOnClassIntegrationTest is present on the classpath"; + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java new file mode 100644 index 0000000000..c0733722dc --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/autoconfiguration/ConditionalOnPropertyIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.autoconfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.TestPropertySource; + +import com.baeldung.autoconfiguration.service.CustomService; +import com.baeldung.autoconfiguration.service.DefaultService; +import com.baeldung.autoconfiguration.service.SimpleService; + +public class ConditionalOnPropertyIntegrationTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenGivenCustomPropertyValue_thenCustomServiceCreated() { + this.contextRunner.withPropertyValues("com.baeldung.service=custom") + .withUserConfiguration(SimpleServiceConfiguration.class) + .run(context -> { + assertThat(context).hasBean("customService"); + SimpleService simpleService = context.getBean(CustomService.class); + assertThat(simpleService.serve()).isEqualTo("Custom Service"); + assertThat(context).doesNotHaveBean("defaultService"); + }); + } + + @Test + public void whenGivenDefaultPropertyValue_thenDefaultServiceCreated() { + this.contextRunner.withPropertyValues("com.baeldung.service=default") + .withUserConfiguration(SimpleServiceConfiguration.class) + .run(context -> { + assertThat(context).hasBean("defaultService"); + SimpleService simpleService = context.getBean(DefaultService.class); + assertThat(simpleService.serve()).isEqualTo("Default Service"); + assertThat(context).doesNotHaveBean("customService"); + }); + } + + @Configuration + @TestPropertySource("classpath:ConditionalOnPropertyTest.properties") + protected static class SimpleServiceConfiguration { + + @Bean + @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "default") + @ConditionalOnMissingBean + public DefaultService defaultService() { + return new DefaultService(); + } + + @Bean + @ConditionalOnProperty(name = "com.baeldung.service", havingValue = "custom") + @ConditionalOnMissingBean + public CustomService customService() { + return new CustomService(); + } + } + +} diff --git a/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties b/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties new file mode 100644 index 0000000000..b6334bc1ce --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/resources/ConditionalOnPropertyTest.properties @@ -0,0 +1 @@ +com.baeldung.service=custom \ No newline at end of file diff --git a/spring-boot-bootstrap/README.md b/spring-boot-bootstrap/README.md index 76b977c129..6a88f25bd7 100644 --- a/spring-boot-bootstrap/README.md +++ b/spring-boot-bootstrap/README.md @@ -1,7 +1,7 @@ ### Relevant Articles: -- [Bootstrap a Simple Application using Spring Boot](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) +- [Spring Boot Tutorial – Bootstrap a Simple Application](http://www.baeldung.com/spring-boot-start) - [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) - [Deploy a Spring Boot Application to OpenShift](https://www.baeldung.com/spring-boot-deploy-openshift) +- [Deploy a Spring Boot Application to AWS Beanstalk](https://www.baeldung.com/spring-boot-deploy-aws-beanstalk) diff --git a/spring-boot-bootstrap/pom.xml b/spring-boot-bootstrap/pom.xml index 7cafc5aa24..70ebb225c8 100644 --- a/spring-boot-bootstrap/pom.xml +++ b/spring-boot-bootstrap/pom.xml @@ -4,16 +4,18 @@ 4.0.0 com.baeldung spring-boot-bootstrap - jar spring-boot-bootstrap Demo project for Spring Boot - + jar + + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT ../parent-boot-2 - + + org.springframework.boot spring-boot-starter-web @@ -57,11 +59,32 @@ + + beanstalk + + ${project.name}-eb + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/cloud/config/*.java + + + + + + openshift 0.3.0.RELEASE - Finchley.SR2 + Greenwich.RELEASE 3.5.37 @@ -143,7 +166,7 @@ org.springframework.cloud spring-cloud-dependencies - Finchley.SR1 + Greenwich.RELEASE pom import @@ -191,7 +214,7 @@ org.springframework.cloud spring-cloud-dependencies - Finchley.SR1 + Greenwich.RELEASE pom import @@ -291,7 +314,8 @@ - + + org.apache.maven.plugins @@ -304,7 +328,8 @@ - + + 4.0.0 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/application-beanstalk.properties b/spring-boot-bootstrap/src/main/resources/application-beanstalk.properties new file mode 100644 index 0000000000..de03a3b5bb --- /dev/null +++ b/spring-boot-bootstrap/src/main/resources/application-beanstalk.properties @@ -0,0 +1,3 @@ +spring.datasource.url=jdbc:mysql://${rds.hostname}:${rds.port}/${rds.db.name} +spring.datasource.username=${rds.username} +spring.datasource.password=${rds.password} \ No newline at end of file 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 + diff --git a/spring-boot-client/pom.xml b/spring-boot-client/pom.xml index fc89931f79..4850849039 100644 --- a/spring-boot-client/pom.xml +++ b/spring-boot-client/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-boot-client 0.0.1-SNAPSHOT - war spring-boot-client + war This is simple boot client application for Spring boot actuator test diff --git a/spring-boot-crud/pom.xml b/spring-boot-crud/pom.xml index 749bf9cb5a..15ff6c5d11 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,9 @@ + + + UTF-8 + + \ No newline at end of file diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md new file mode 100644 index 0000000000..3fd1d17994 --- /dev/null +++ b/spring-boot-data/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: +- [Formatting JSON Dates in Spring Boot](https://www.baeldung.com/spring-boot-formatting-json-dates) +- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json) diff --git a/spring-boot-data/pom.xml b/spring-boot-data/pom.xml new file mode 100644 index 0000000000..9c11e09f4a --- /dev/null +++ b/spring-boot-data/pom.xml @@ -0,0 +1,146 @@ + + + 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-data-redis + 2.1.6.RELEASE + + + + org.springframework.boot + spring-boot-starter-data-mongodb + 2.1.6.RELEASE + + + + org.springframework.boot + spring-boot-starter-data-jpa + 2.1.6.RELEASE + + + + com.h2database + h2 + 1.4.197 + + + + 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 + + + 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/disableautoconfig/SpringDataJPA.java b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataJPA.java new file mode 100644 index 0000000000..8e4ee76a25 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataJPA.java @@ -0,0 +1,16 @@ +package com.baeldung.disableautoconfig; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; + +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) +public class SpringDataJPA { + + public static void main(String[] args) { + SpringApplication.run(SpringDataJPA.class, args); + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataMongoDB.java b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataMongoDB.java new file mode 100644 index 0000000000..865c137a8d --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataMongoDB.java @@ -0,0 +1,14 @@ +package com.baeldung.disableautoconfig; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; + +@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) +public class SpringDataMongoDB { + + public static void main(String[] args) { + SpringApplication.run(SpringDataMongoDB.class, args); + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataRedis.java b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataRedis.java new file mode 100644 index 0000000000..9ec831c446 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/disableautoconfig/SpringDataRedis.java @@ -0,0 +1,14 @@ +package com.baeldung.disableautoconfig; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration; + +@SpringBootApplication(exclude = {RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class}) +public class SpringDataRedis { + + public static void main(String[] args) { + SpringApplication.run(SpringDataRedis.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/java/com/baeldung/jsonexception/CustomException.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java new file mode 100644 index 0000000000..f1a1d94f54 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java @@ -0,0 +1,11 @@ +package com.baeldung.jsonexception; + +public class CustomException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CustomException() { + super("Custom exception message."); + } + +} \ No newline at end of file diff --git a/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java new file mode 100644 index 0000000000..9f82c4fc57 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java @@ -0,0 +1,17 @@ +package com.baeldung.jsonexception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ErrorHandler { + + @ExceptionHandler(CustomException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public CustomException handleCustomException(CustomException ce) { + return ce; + } + +} \ No newline at end of file diff --git a/spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java new file mode 100644 index 0000000000..5d73c239a4 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java @@ -0,0 +1,14 @@ +package com.baeldung.jsonexception; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class MainController { + + @GetMapping("/") + public void index() throws CustomException { + throw new CustomException(); + } + +} \ No newline at end of file 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/disableautoconfig/SpringDataJPAIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataJPAIntegrationTest.java new file mode 100644 index 0000000000..a465979b3c --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataJPAIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.disableautoconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.sql.DataSource; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringDataJPA.class) +public class SpringDataJPAIntegrationTest { + + @Autowired + private ApplicationContext context; + + @Test(expected = NoSuchBeanDefinitionException.class) + public void givenAutoconfigurationIsDisable_whenApplicationStarts_thenContextWillNotHaveTheAutoconfiguredClasses() { + context.getBean(DataSource.class); + } + +} diff --git a/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataMongoDBIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataMongoDBIntegrationTest.java new file mode 100644 index 0000000000..bdfadf76ce --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataMongoDBIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.disableautoconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringDataMongoDB.class) +public class SpringDataMongoDBIntegrationTest { + + @Autowired + private ApplicationContext context; + + @Test(expected = NoSuchBeanDefinitionException.class) + public void givenAutoconfigurationIsDisable_whenApplicationStarts_thenContextWillNotHaveTheAutoconfiguredClasses() { + context.getBean(MongoTemplate.class); + } + +} diff --git a/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataRedisIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataRedisIntegrationTest.java new file mode 100644 index 0000000000..10133cace3 --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/disableautoconfig/SpringDataRedisIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.disableautoconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringDataRedis.class) +public class SpringDataRedisIntegrationTest { + + @Autowired + private ApplicationContext context; + + @Test(expected = NoSuchBeanDefinitionException.class) + public void givenAutoconfigurationIsDisable_whenApplicationStarts_thenContextWillNotHaveTheAutoconfiguredClasses() { + context.getBean(RedisTemplate.class); + } + +} 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/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java new file mode 100644 index 0000000000..77e71b7d21 --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java @@ -0,0 +1,19 @@ +package com.baeldung.jsonexception; + +import org.junit.Test; + +import com.baeldung.jsonexception.CustomException; +import com.baeldung.jsonexception.MainController; + +public class MainControllerIntegrationTest { + + @Test(expected = CustomException.class) + public void givenIndex_thenCustomException() throws CustomException { + + MainController mainController = new MainController(); + + mainController.index(); + + } + +} \ No newline at end of file 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-disable-console-logging/disabling-console-jul/pom.xml b/spring-boot-disable-console-logging/disabling-console-jul/pom.xml index 9ccbd56231..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,10 @@ - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - + 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 0b360bb366..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,10 @@ - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE +
diff --git a/spring-boot-exceptions/README.md b/spring-boot-exceptions/README.md new file mode 100644 index 0000000000..bbc272aec4 --- /dev/null +++ b/spring-boot-exceptions/README.md @@ -0,0 +1,4 @@ + +### Relevant Articles: + +- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json) diff --git a/spring-boot-flowable/README.md b/spring-boot-flowable/README.md new file mode 100644 index 0000000000..8fb90d953b --- /dev/null +++ b/spring-boot-flowable/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Introduction to Flowable](http://www.baeldung.com/flowable) diff --git a/spring-boot-flowable/pom.xml b/spring-boot-flowable/pom.xml new file mode 100644 index 0000000000..f7fc943389 --- /dev/null +++ b/spring-boot-flowable/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + spring-boot-flowable + war + spring-boot-flowable + Spring Boot Flowable Module + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + com.h2database + h2 + runtime + + + org.flowable + flowable-spring-boot-starter-rest + ${flowable.version} + + + org.flowable + flowable-spring-boot-starter-actuator + ${flowable.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 6.4.1 + + \ No newline at end of file diff --git a/spring-boot-flowable/src/main/java/com/baeldung/Application.java b/spring-boot-flowable/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..37dbe7dab8 --- /dev/null +++ b/spring-boot-flowable/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/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java b/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java new file mode 100644 index 0000000000..3087d30af4 --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java @@ -0,0 +1,32 @@ +package com.baeldung.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.domain.Approval; +import com.baeldung.domain.Article; +import com.baeldung.service.ArticleWorkflowService; + +@RestController +public class ArticleWorkflowController { + @Autowired + private ArticleWorkflowService service; + @PostMapping("/submit") + public void submit(@RequestBody Article article) { + service.startProcess(article); + } + @GetMapping("/tasks") + public List
getTasks(@RequestParam String assignee) { + return service.getTasks(assignee); + } + @PostMapping("/review") + public void review(@RequestBody Approval approval) { + service.submitReview(approval); + } +} \ No newline at end of file diff --git a/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java b/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java new file mode 100644 index 0000000000..b0c9c99437 --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java @@ -0,0 +1,24 @@ +package com.baeldung.domain; + +public class Approval { + + private String id; + private boolean status; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public boolean isStatus() { + return status; + } + + public void setStatus(boolean status) { + this.status = status; + } + +} diff --git a/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java b/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java new file mode 100644 index 0000000000..efa2eb431e --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java @@ -0,0 +1,52 @@ +package com.baeldung.domain; + +public class Article { + + private String id; + private String author; + private String url; + + public Article() { + } + + public Article(String author, String url) { + this.author = author; + this.url = url; + } + + public Article(String id, String author, String url) { + this.id = id; + this.author = author; + this.url = url; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return ("[" + this.author + " " + this.url + "]"); + } + +} diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java new file mode 100644 index 0000000000..b1e2a92354 --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java @@ -0,0 +1,55 @@ +package com.baeldung.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; +import org.flowable.task.api.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.domain.Approval; +import com.baeldung.domain.Article; + +@Service +public class ArticleWorkflowService { + @Autowired + private RuntimeService runtimeService; + @Autowired + private TaskService taskService; + + @Transactional + public void startProcess(Article article) { + Map variables = new HashMap(); + variables.put("author", article.getAuthor()); + variables.put("url", article.getUrl()); + runtimeService.startProcessInstanceByKey("articleReview", variables); + } + + @Transactional + public List
getTasks(String assignee) { + List tasks = taskService.createTaskQuery() + .taskCandidateGroup(assignee) + .list(); + + List
articles = tasks.stream() + .map(task -> { + Map variables = taskService.getVariables(task.getId()); + return new Article( + task.getId(), (String) variables.get("author"), (String) variables.get("url")); + }) + .collect(Collectors.toList()); + return articles; + } + + @Transactional + public void submitReview(Approval approval) { + Map variables = new HashMap(); + variables.put("approved", approval.isStatus()); + taskService.complete(approval.getId(), variables); + } +} \ No newline at end of file diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java new file mode 100644 index 0000000000..b43f1dccdb --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java @@ -0,0 +1,10 @@ +package com.baeldung.service; + +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; + +public class PublishArticleService implements JavaDelegate { + public void execute(DelegateExecution execution) { + System.out.println("Publishing the approved article."); + } +} diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java new file mode 100644 index 0000000000..f80b16748f --- /dev/null +++ b/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java @@ -0,0 +1,10 @@ +package com.baeldung.service; + +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; + +public class SendMailService implements JavaDelegate { + public void execute(DelegateExecution execution) { + System.out.println("Sending rejection mail to author."); + } +} diff --git a/spring-boot-flowable/src/main/resources/application.properties b/spring-boot-flowable/src/main/resources/application.properties new file mode 100644 index 0000000000..c3afcaa0b5 --- /dev/null +++ b/spring-boot-flowable/src/main/resources/application.properties @@ -0,0 +1 @@ +management.endpoint.flowable.enabled=true \ No newline at end of file diff --git a/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml b/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml new file mode 100644 index 0000000000..77c02f39a4 --- /dev/null +++ b/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowIntegrationTest.java b/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowIntegrationTest.java new file mode 100644 index 0000000000..7d4557a679 --- /dev/null +++ b/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowIntegrationTest.java @@ -0,0 +1,40 @@ +package com.baeldung.processes; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; +import org.flowable.engine.test.Deployment; +import org.flowable.spring.impl.test.FlowableSpringExtension; +import org.flowable.task.api.Task; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@ExtendWith(FlowableSpringExtension.class) +@SpringBootTest +public class ArticleWorkflowIntegrationTest { + @Autowired + private RuntimeService runtimeService; + @Autowired + private TaskService taskService; + @Test + @Deployment(resources = { "processes/article-workflow.bpmn20.xml" }) + void articleApprovalTest() { + Map variables = new HashMap(); + variables.put("author", "test@baeldung.com"); + variables.put("url", "http://baeldung.com/dummy"); + runtimeService.startProcessInstanceByKey("articleReview", variables); + Task task = taskService.createTaskQuery() + .singleResult(); + assertEquals("Review the submitted tutorial", task.getName()); + variables.put("approved", true); + taskService.complete(task.getId(), variables); + assertEquals(0, runtimeService.createProcessInstanceQuery() + .count()); + } +} \ No newline at end of file diff --git a/spring-boot-jasypt/pom.xml b/spring-boot-jasypt/pom.xml index de0df92678..ae0483f107 100644 --- a/spring-boot-jasypt/pom.xml +++ b/spring-boot-jasypt/pom.xml @@ -2,11 +2,10 @@ 4.0.0 - com.example.jasypt spring-boot-jasypt - jar spring-boot-jasypt + jar Demo project for Spring Boot diff --git a/spring-boot-keycloak/pom.xml b/spring-boot-keycloak/pom.xml index 3a39d4aa94..b13805b4bf 100644 --- a/spring-boot-keycloak/pom.xml +++ b/spring-boot-keycloak/pom.xml @@ -5,9 +5,9 @@ com.baeldung.keycloak spring-boot-keycloak 0.0.1 - jar spring-boot-keycloak This is a simple application demonstrating integration between Keycloak and Spring Boot. + jar com.baeldung 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 diff --git a/spring-boot-libraries/.gitignore b/spring-boot-libraries/.gitignore new file mode 100644 index 0000000000..da7c2c5c0a --- /dev/null +++ b/spring-boot-libraries/.gitignore @@ -0,0 +1,5 @@ +/target/ +.settings/ +.classpath +.project + diff --git a/spring-boot-libraries/.mvn/wrapper/maven-wrapper.jar b/spring-boot-libraries/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000..5fd4d5023f Binary files /dev/null and b/spring-boot-libraries/.mvn/wrapper/maven-wrapper.jar differ diff --git a/spring-boot-libraries/README.MD b/spring-boot-libraries/README.MD new file mode 100644 index 0000000000..f3706e0fa4 --- /dev/null +++ b/spring-boot-libraries/README.MD @@ -0,0 +1,7 @@ +### The Course +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) diff --git a/spring-boot-libraries/mvnw b/spring-boot-libraries/mvnw new file mode 100644 index 0000000000..e96ccd5fbb --- /dev/null +++ b/spring-boot-libraries/mvnw @@ -0,0 +1,227 @@ +#!/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 + +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-libraries/mvnw.cmd b/spring-boot-libraries/mvnw.cmd new file mode 100644 index 0000000000..6a6eec39ba --- /dev/null +++ b/spring-boot-libraries/mvnw.cmd @@ -0,0 +1,145 @@ +@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 + +%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-libraries/pom.xml b/spring-boot-libraries/pom.xml new file mode 100644 index 0000000000..b448d6fd66 --- /dev/null +++ b/spring-boot-libraries/pom.xml @@ -0,0 +1,157 @@ + + 4.0.0 + spring-boot-libraries + spring-boot-libraries + war + This is simple boot application for Spring boot actuator test + + + 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-security + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.zalando + problem-spring-web + ${problem-spring-web.version} + + + + + net.javacrumbs.shedlock + shedlock-spring + ${shedlock.version} + + + net.javacrumbs.shedlock + shedlock-provider-jdbc-template + ${shedlock.version} + + + + + + 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.intro.App + 8.5.11 + 2.4.1.Final + 1.9.0 + 2.0.0 + 5.0.2 + 5.0.2 + 5.2.4 + 18.0 + 2.2.4 + 2.3.2 + 0.23.0 + 2.1.0 + + + diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java new file mode 100644 index 0000000000..cb0d0c1532 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java @@ -0,0 +1,14 @@ +package com.baeldung.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; + +@SpringBootApplication +public class Application { + private static ApplicationContext applicationContext; + + public static void main(String[] args) { + applicationContext = SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java new file mode 100644 index 0000000000..7ca9881fb9 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.boot.problem; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) +@ComponentScan("com.baeldung.boot.problem") +public class SpringProblemApplication { + + public static void main(String[] args) { + System.setProperty("spring.profiles.active", "problem"); + SpringApplication.run(SpringProblemApplication.class, args); + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java new file mode 100644 index 0000000000..18df103733 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java @@ -0,0 +1,16 @@ +package com.baeldung.boot.problem.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.zalando.problem.spring.web.advice.ProblemHandling; + +@ControllerAdvice +public class ExceptionHandler implements ProblemHandling { + + // The causal chain of causes is disabled by default, + // but we can easily enable it by overriding the behavior: + @Override + public boolean isCausalChainsEnabled() { + return true; + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java new file mode 100644 index 0000000000..8013cbf5c3 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java @@ -0,0 +1,9 @@ +package com.baeldung.boot.problem.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait; + +@ControllerAdvice +public class SecurityExceptionHandler implements SecurityAdviceTrait { + +} \ No newline at end of file diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java new file mode 100644 index 0000000000..f5e6a6b99a --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java @@ -0,0 +1,19 @@ +package com.baeldung.boot.problem.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.zalando.problem.ProblemModule; +import org.zalando.problem.validation.ConstraintViolationProblemModule; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Configuration +public class ProblemDemoConfiguration { + + @Bean + public ObjectMapper objectMapper() { + // In this example, stack traces support is enabled by default. + // If you want to disable stack traces just use new ProblemModule() instead of new ProblemModule().withStackTraces() + return new ObjectMapper().registerModules(new ProblemModule().withStackTraces(), new ConstraintViolationProblemModule()); + } +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java new file mode 100644 index 0000000000..0cb8048981 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java @@ -0,0 +1,31 @@ +package com.baeldung.boot.problem.configuration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +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.zalando.problem.spring.web.advice.security.SecurityProblemSupport; + +@Configuration +@EnableWebSecurity +@Import(SecurityProblemSupport.class) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private SecurityProblemSupport problemSupport; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable(); + + http.authorizeRequests() + .antMatchers("/") + .permitAll(); + + http.exceptionHandling() + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport); + } +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java new file mode 100644 index 0000000000..50f1ad5137 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java @@ -0,0 +1,56 @@ +package com.baeldung.boot.problem.controller; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.boot.problem.dto.Task; +import com.baeldung.boot.problem.problems.TaskNotFoundProblem; + +@RestController +@RequestMapping("/tasks") +public class ProblemDemoController { + + private static final Map MY_TASKS; + + static { + MY_TASKS = new HashMap<>(); + MY_TASKS.put(1L, new Task(1L, "My first task")); + MY_TASKS.put(2L, new Task(2L, "My second task")); + } + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public List getTasks() { + return new ArrayList<>(MY_TASKS.values()); + } + + @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public Task getTasks(@PathVariable("id") Long taskId) { + if (MY_TASKS.containsKey(taskId)) { + return MY_TASKS.get(taskId); + } else { + throw new TaskNotFoundProblem(taskId); + } + } + + @PutMapping("/{id}") + public void updateTask(@PathVariable("id") Long id) { + throw new UnsupportedOperationException(); + } + + @DeleteMapping("/{id}") + public void deleteTask(@PathVariable("id") Long id) { + throw new AccessDeniedException("You can't delete this task"); + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java new file mode 100644 index 0000000000..a5f39474e7 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java @@ -0,0 +1,32 @@ +package com.baeldung.boot.problem.dto; + +public class Task { + + private Long id; + private String description; + + public Task() { + } + + public Task(Long id, String description) { + this.id = id; + this.description = description; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java new file mode 100644 index 0000000000..cc3f21d4a5 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java @@ -0,0 +1,16 @@ +package com.baeldung.boot.problem.problems; + +import java.net.URI; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +public class TaskNotFoundProblem extends AbstractThrowableProblem { + + private static final URI TYPE = URI.create("https://example.org/not-found"); + + public TaskNotFoundProblem(Long taskId) { + super(TYPE, "Not found", Status.NOT_FOUND, String.format("Task '%s' not found", taskId)); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/scheduling/shedlock/SchedulerConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java similarity index 100% rename from spring-all/src/main/java/org/baeldung/scheduling/shedlock/SchedulerConfiguration.java rename to spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java diff --git a/spring-all/src/main/java/org/baeldung/scheduling/shedlock/TaskScheduler.java b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java similarity index 91% rename from spring-all/src/main/java/org/baeldung/scheduling/shedlock/TaskScheduler.java rename to spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java index b1b1ad921f..060afe660e 100644 --- a/spring-all/src/main/java/org/baeldung/scheduling/shedlock/TaskScheduler.java +++ b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java @@ -7,9 +7,9 @@ import org.springframework.stereotype.Component; @Component class TaskScheduler { - @Scheduled(cron = "*/15 * * * * *") + @Scheduled(cron = "*/15 * * * *") @SchedulerLock(name = "TaskScheduler_scheduledTask", lockAtLeastForString = "PT5M", lockAtMostForString = "PT14M") public void scheduledTask() { System.out.println("Running ShedLock task"); } -} \ No newline at end of file +} diff --git a/spring-boot-libraries/src/main/resources/application-problem.properties b/spring-boot-libraries/src/main/resources/application-problem.properties new file mode 100644 index 0000000000..7d0b0a2720 --- /dev/null +++ b/spring-boot-libraries/src/main/resources/application-problem.properties @@ -0,0 +1,3 @@ +spring.resources.add-mappings=false +spring.mvc.throw-exception-if-no-handler-found=true +spring.http.encoding.force=true diff --git a/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java new file mode 100644 index 0000000000..5ced1034c4 --- /dev/null +++ b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java @@ -0,0 +1,101 @@ +package com.baeldung.boot.problem.controller; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +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.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +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 com.baeldung.boot.problem.SpringProblemApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = SpringProblemApplication.class) +@AutoConfigureMockMvc +public class ProblemDemoControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenRequestingAllTasks_thenReturnSuccessfulResponseWithArrayWithTwoTasks() throws Exception { + mockMvc.perform(get("/tasks").contentType(MediaType.APPLICATION_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.length()", equalTo(2))) + .andExpect(status().isOk()); + } + + @Test + public void whenRequestingExistingTask_thenReturnSuccessfulResponse() throws Exception { + mockMvc.perform(get("/tasks/1").contentType(MediaType.APPLICATION_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.id", equalTo(1))) + .andExpect(status().isOk()); + } + + @Test + public void whenRequestingMissingTask_thenReturnNotFoundProblemResponse() throws Exception { + mockMvc.perform(get("/tasks/5").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Not found"))) + .andExpect(jsonPath("$.status", equalTo(404))) + .andExpect(jsonPath("$.detail", equalTo("Task '5' not found"))) + .andExpect(status().isNotFound()); + } + + @Test + public void whenMakePutCall_thenReturnNotImplementedProblemResponse() throws Exception { + mockMvc.perform(put("/tasks/1").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Not Implemented"))) + .andExpect(jsonPath("$.status", equalTo(501))) + .andExpect(status().isNotImplemented()); + } + + @Test + public void whenMakeDeleteCall_thenReturnForbiddenProblemResponse() throws Exception { + mockMvc.perform(delete("/tasks/2").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Forbidden"))) + .andExpect(jsonPath("$.status", equalTo(403))) + .andExpect(jsonPath("$.detail", equalTo("You can't delete this task"))) + .andExpect(status().isForbidden()); + } + + @Test + public void whenMakeGetCallWithInvalidIdFormat_thenReturnBadRequestResponseWithStackTrace() throws Exception { + mockMvc.perform(get("/tasks/invalid-id").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Bad Request"))) + .andExpect(jsonPath("$.status", equalTo(400))) + .andExpect(jsonPath("$.stacktrace", notNullValue())) + .andExpect(status().isBadRequest()); + } + + @Test + public void whenMakeGetCallWithInvalidIdFormat_thenReturnBadRequestResponseWithCause() throws Exception { + mockMvc.perform(get("/tasks/invalid-id").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Bad Request"))) + .andExpect(jsonPath("$.status", equalTo(400))) + .andExpect(jsonPath("$.cause", notNullValue())) + .andExpect(jsonPath("$.cause.title", equalTo("Internal Server Error"))) + .andExpect(jsonPath("$.cause.status", equalTo(500))) + .andExpect(jsonPath("$.cause.detail", containsString("For input string:"))) + .andExpect(jsonPath("$.cause.stacktrace", notNullValue())) + .andExpect(status().isBadRequest()); + } + +} diff --git a/spring-boot-logging-log4j2/pom.xml b/spring-boot-logging-log4j2/pom.xml index ad678a14cf..6cc60da52c 100644 --- a/spring-boot-logging-log4j2/pom.xml +++ b/spring-boot-logging-log4j2/pom.xml @@ -3,8 +3,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-boot-logging-log4j2 - jar spring-boot-logging-log4j2 + jar Demo project for Spring Boot Logging with Log4J2 @@ -40,12 +40,12 @@ org.springframework.boot spring-boot-starter-log4j - 1.3.8.RELEASE + ${spring-boot-starter-log4j.version} org.graylog2 gelfj - 1.1.16 + ${gelfj.version} compile @@ -71,5 +71,7 @@ com.baeldung.springbootlogging.SpringBootLoggingApplication + 1.3.8.RELEASE + 1.1.16 diff --git a/spring-boot-mvc-birt/README.md b/spring-boot-mvc-birt/README.md new file mode 100644 index 0000000000..9fe3d94e2a --- /dev/null +++ b/spring-boot-mvc-birt/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [BIRT Reporting with Spring Boot](https://www.baeldung.com/birt-reports-spring-boot) diff --git a/spring-boot-mvc-birt/pom.xml b/spring-boot-mvc-birt/pom.xml new file mode 100644 index 0000000000..6feb2a7611 --- /dev/null +++ b/spring-boot-mvc-birt/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + com.baeldung + spring-boot-mvc-birt + spring-boot-mvc-birt + 0.0.1-SNAPSHOT + jar + Module For Spring Boot Integration with BIRT + + + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-logging + + + ch.qos.logback + logback-classic + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.innoventsolutions.birt.runtime + org.eclipse.birt.runtime_4.8.0-20180626 + 4.8.0 + + + + log4j + log4j + 1.2.17 + + + + org.projectlombok + lombok + 1.18.6 + provided + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 2.1.1.RELEASE + com.baeldung.birt.engine.ReportEngineApplication + 1.8 + 1.8 + + + diff --git a/spring-boot-mvc-birt/reports/csv_data_report.rptdesign b/spring-boot-mvc-birt/reports/csv_data_report.rptdesign new file mode 100644 index 0000000000..f390c5e69b --- /dev/null +++ b/spring-boot-mvc-birt/reports/csv_data_report.rptdesign @@ -0,0 +1,2032 @@ + + + Eclipse BIRT Designer Version 4.7.0.v201706222054 + new_report + + + queryText + 5 + + + HOME + 4 + + + URI + 4 + + + DELIMTYPE + 4 + + + CHARSET + 4 + + + INCLCOLUMNNAME + 4 + + + INCLTYPELINE + 4 + + + TRAILNULLCOLS + 4 + + + OdaConnProfileName + 4 + + + OdaConnProfileStorePath + 4 + + + in + /templates/blank_report.gif + ltr + 96 + + + reports/data.csv + COMMA + UTF-8 + YES + NO + NO + + + + + nulls lowest + + + Student + dimension + Student + + + Math + measure + Math + + + Geography + measure + Geography + + + History + measure + History + + + + + + + 1 + Student + string + + + 2 + Math + integer + + + 3 + Geography + integer + + + 4 + History + integer + + + + Data Source + + + 1 + Student + Student + string + 12 + + + 2 + Math + Math + integer + 12 + + + 3 + Geography + Geography + integer + 12 + + + 4 + History + History + integer + 12 + + + + + + 2.0 + + + + + + + Studen + 1 + + 12 + -1 + -1 + Unknown + + + Studen + + + + + + + Math + 2 + + 12 + -1 + -1 + Unknown + + + Math + + + + + + + Geography + 3 + + 12 + -1 + -1 + Unknown + + + Geography + + + + + + + History + 4 + + 12 + -1 + -1 + Unknown + + + History + + + + + + + +]]> + + + + + + + + + + + + 7.947916666666667in + + 2.15625in + + + + + 2 + 1 + + + 2.6.1 + Bar Chart + Side-by-side + + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 3.0 + 3.0 + 3.0 + 3.0 + + -1 + -1 + -1 + -1 + + + 1 + + 255 + 0 + 0 + 0 + + false + + true + + + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 3.0 + 3.0 + 3.0 + 3.0 + + -1 + -1 + -1 + -1 + + + 1 + + 255 + 0 + 0 + 0 + + false + + true + 5 + 5 + + + + 0 + + 255 + 0 + 0 + 0 + + false + + + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 3.0 + 3.0 + 3.0 + 3.0 + + -1 + -1 + -1 + -1 + + + 1 + + 255 + 0 + 0 + 0 + + false + + true + + + + 0 + + 255 + 0 + 0 + 0 + + false + + + 2.0 + 2.0 + 2.0 + 2.0 + + + + + + + + + Vertical + Top_Bottom + + + 1 + + 255 + 0 + 0 + 0 + + true + + Right + Series + + <Caption> + <Value></Value> + <Font> + <Alignment/> + </Font> + </Caption> + <Background xsi:type="attribute:ColorDefinition"> + <Transparency>0</Transparency> + <Red>255</Red> + <Green>255</Green> + <Blue>255</Blue> + </Background> + <Outline> + <Style>Solid</Style> + <Thickness>1</Thickness> + <Color> + <Transparency>255</Transparency> + <Red>0</Red> + <Green>0</Green> + <Blue>0</Blue> + </Color> + <Visible>false</Visible> + </Outline> + <Insets> + <Top>0.0</Top> + <Left>2.0</Left> + <Bottom>0.0</Bottom> + <Right>3.0</Right> + </Insets> + <Visible>false</Visible> + + Above + false + + + 0.0 + 0.0 + 572.25 + 286.125 + + + 3.0 + 3.0 + 3.0 + 3.0 + + -1 + -1 + -1 + -1 + + + 1 + + 255 + 0 + 0 + 0 + + false + + true + + Two_Dimensional + Points + 10.0 + + enable.area.alt + false + + + + A, B, C + + + 5,4,12 + 0 + + + 10.0,8.0,24.0 + 1 + + + 15.0,12.0,36.0 + 2 + + + + ToggleSerieVisibility + + + + This chart contains no data. + + + Center + Center + + + + + 64 + 127 + 127 + 127 + + + + 128 + 127 + 127 + 127 + + true + + + 10.0 + 10.0 + 10.0 + 10.0 + + false + + + Text + + <Caption> + <Value>X-Axis Title</Value> + <Font> + <Size>14.0</Size> + <Bold>true</Bold> + <Alignment> + <horizontalAlignment>Center</horizontalAlignment> + <verticalAlignment>Center</verticalAlignment> + </Alignment> + </Font> + </Caption> + <Background xsi:type="attribute:ColorDefinition"> + <Transparency>0</Transparency> + <Red>255</Red> + <Green>255</Green> + <Blue>255</Blue> + </Background> + <Outline> + <Style>Solid</Style> + <Thickness>1</Thickness> + <Color> + <Transparency>255</Transparency> + <Red>0</Red> + <Green>0</Green> + <Blue>0</Blue> + </Color> + </Outline> + <Insets> + <Top>0.0</Top> + <Left>2.0</Left> + <Bottom>0.0</Bottom> + <Right>3.0</Right> + </Insets> + <Visible>false</Visible> + + Below + + Linear + + <Caption> + <Value>Y-Axis Title</Value> + <Font> + <Size>14.0</Size> + <Bold>true</Bold> + <Alignment> + <horizontalAlignment>Center</horizontalAlignment> + <verticalAlignment>Center</verticalAlignment> + </Alignment> + </Font> + </Caption> + <Background xsi:type="attribute:ColorDefinition"> + <Transparency>0</Transparency> + <Red>255</Red> + <Green>255</Green> + <Blue>255</Blue> + </Background> + <Outline> + <Style>Solid</Style> + <Thickness>1</Thickness> + <Color> + <Transparency>255</Transparency> + <Red>0</Red> + <Green>0</Green> + <Blue>0</Blue> + </Color> + </Outline> + <Insets> + <Top>0.0</Top> + <Left>2.0</Left> + <Bottom>0.0</Bottom> + <Right>3.0</Right> + </Insets> + <Visible>false</Visible> + + Left + + + + + Numeric + + + + + 255 + 80 + 166 + 218 + + + 255 + 242 + 88 + 106 + + + 255 + 232 + 172 + 57 + + + 255 + 128 + 255 + 128 + + + 255 + 64 + 128 + 128 + + + 255 + 128 + 128 + 192 + + + 255 + 170 + 85 + 85 + + + 255 + 128 + 128 + 0 + + + 255 + 192 + 192 + 192 + + + 255 + 255 + 255 + 128 + + + 255 + 128 + 192 + 128 + + + 255 + 7 + 146 + 94 + + + 255 + 0 + 128 + 255 + + + 255 + 255 + 128 + 192 + + + 255 + 0 + 255 + 255 + + + 255 + 255 + 128 + 128 + + + 255 + 0 + 128 + 192 + + + 255 + 255 + 0 + 255 + + + 255 + 128 + 64 + 64 + + + 255 + 255 + 128 + 64 + + + 255 + 80 + 240 + 120 + + + 255 + 0 + 64 + 128 + + + 255 + 128 + 0 + 64 + + + 255 + 255 + 0 + 128 + + + 255 + 128 + 128 + 64 + + + 255 + 128 + 128 + 128 + + + 255 + 255 + 128 + 255 + + + 255 + 0 + 64 + 0 + + + 255 + 0 + 0 + 0 + + + 255 + 255 + 255 + 255 + + + 255 + 255 + 128 + 0 + + + + true + + + row["Geography"] + + Text + Sum + + + Geo + + + Orthogonal_Value + + , + + Outside + false + + onmouseover + + Show_Tooltip + + + 200 + + + + Rectangle + + + Text + Sum + + + + + + + Numeric + + + + + 255 + 242 + 88 + 106 + + + 255 + 232 + 172 + 57 + + + 255 + 128 + 255 + 128 + + + 255 + 64 + 128 + 128 + + + 255 + 128 + 128 + 192 + + + 255 + 170 + 85 + 85 + + + 255 + 128 + 128 + 0 + + + 255 + 192 + 192 + 192 + + + 255 + 255 + 255 + 128 + + + 255 + 128 + 192 + 128 + + + 255 + 7 + 146 + 94 + + + 255 + 0 + 128 + 255 + + + 255 + 255 + 128 + 192 + + + 255 + 0 + 255 + 255 + + + 255 + 255 + 128 + 128 + + + 255 + 0 + 128 + 192 + + + 255 + 255 + 0 + 255 + + + 255 + 128 + 64 + 64 + + + 255 + 255 + 128 + 64 + + + 255 + 80 + 240 + 120 + + + 255 + 0 + 64 + 128 + + + 255 + 128 + 0 + 64 + + + 255 + 255 + 0 + 128 + + + 255 + 128 + 128 + 64 + + + 255 + 128 + 128 + 128 + + + 255 + 255 + 128 + 255 + + + 255 + 0 + 64 + 0 + + + 255 + 0 + 0 + 0 + + + 255 + 255 + 255 + 255 + + + 255 + 255 + 128 + 0 + + + 255 + 80 + 166 + 218 + + + + true + + + row["History"] + + false + Text + Sum + + + History + + + Orthogonal_Value + + , + + Outside + false + + onmouseover + + Show_Tooltip + + + 200 + + + + Rectangle + + + Text + Sum + + + + + + + Numeric + + + + + 255 + 232 + 172 + 57 + + + 255 + 128 + 255 + 128 + + + 255 + 64 + 128 + 128 + + + 255 + 128 + 128 + 192 + + + 255 + 170 + 85 + 85 + + + 255 + 128 + 128 + 0 + + + 255 + 192 + 192 + 192 + + + 255 + 255 + 255 + 128 + + + 255 + 128 + 192 + 128 + + + 255 + 7 + 146 + 94 + + + 255 + 0 + 128 + 255 + + + 255 + 255 + 128 + 192 + + + 255 + 0 + 255 + 255 + + + 255 + 255 + 128 + 128 + + + 255 + 0 + 128 + 192 + + + 255 + 255 + 0 + 255 + + + 255 + 128 + 64 + 64 + + + 255 + 255 + 128 + 64 + + + 255 + 80 + 240 + 120 + + + 255 + 0 + 64 + 128 + + + 255 + 128 + 0 + 64 + + + 255 + 255 + 0 + 128 + + + 255 + 128 + 128 + 64 + + + 255 + 128 + 128 + 128 + + + 255 + 255 + 128 + 255 + + + 255 + 0 + 64 + 0 + + + 255 + 0 + 0 + 0 + + + 255 + 255 + 255 + 255 + + + 255 + 255 + 128 + 0 + + + 255 + 80 + 166 + 218 + + + 255 + 242 + 88 + 106 + + + + true + + + row["Math"] + + false + Text + Sum + + + Math + + + Orthogonal_Value + + , + + Outside + false + + onmouseover + + Show_Tooltip + + + 200 + + + + Rectangle + + + Text + Sum + + + Vertical + + + 1 + + 255 + 0 + 0 + 0 + + true + + + Left + + + + 1 + + 255 + 196 + 196 + 196 + + false + + Across + + + 1 + + 255 + 196 + 196 + 196 + + true + + + + + + 1 + + 255 + 225 + 225 + 225 + + false + + Across + + + 1 + + 255 + 225 + 225 + 225 + + false + + + + 5 + + + Min + + 0.0 + + + true + false + + + + + + + + 255 + 80 + 166 + 218 + + + 255 + 242 + 88 + 106 + + + 255 + 232 + 172 + 57 + + + 255 + 128 + 255 + 128 + + + 255 + 64 + 128 + 128 + + + 255 + 128 + 128 + 192 + + + 255 + 170 + 85 + 85 + + + 255 + 128 + 128 + 0 + + + 255 + 192 + 192 + 192 + + + 255 + 255 + 255 + 128 + + + 255 + 128 + 192 + 128 + + + 255 + 7 + 146 + 94 + + + 255 + 0 + 128 + 255 + + + 255 + 255 + 128 + 192 + + + 255 + 0 + 255 + 255 + + + 255 + 255 + 128 + 128 + + + 255 + 0 + 128 + 192 + + + 255 + 255 + 0 + 255 + + + 255 + 128 + 64 + 64 + + + 255 + 255 + 128 + 64 + + + 255 + 80 + 240 + 120 + + + 255 + 0 + 64 + 128 + + + 255 + 128 + 0 + 64 + + + 255 + 255 + 0 + 128 + + + 255 + 128 + 128 + 64 + + + 255 + 128 + 128 + 128 + + + 255 + 255 + 128 + 255 + + + 255 + 0 + 64 + 0 + + + 255 + 0 + 0 + 0 + + + 255 + 255 + 255 + 255 + + + 255 + 255 + 128 + 0 + + + + true + + + row["Student"] + + + + + Orthogonal_Value + + , + + Outside + false + + + true + Text + Sum + + + Horizontal + + + 1 + + 255 + 0 + 0 + 0 + + true + + + Below + + + + 1 + + 255 + 196 + 196 + 196 + + false + + Across + + + 1 + + 255 + 196 + 196 + 196 + + true + + + + + + 1 + + 255 + 225 + 225 + 225 + + false + + Across + + + 1 + + 255 + 225 + 225 + 225 + + false + + + + 5 + + + Min + + 0.0 + + + true + true + false + + Vertical + 50.0 + + + -20.0 + 45.0 + 0.0 + None + + + +]]> + SVG + true + 286.125pt + 572.25pt + Data Set + + + Student + Student + dataSetRow["Student"] + string + + + Math + Math + dataSetRow["Math"] + integer + + + Geography + Geography + dataSetRow["Geography"] + integer + + + History + History + dataSetRow["History"] + integer + + + + + + + + 2 + 1 + + Data Set + + + Student + Student + dataSetRow["Student"] + string + + + Math + Math + dataSetRow["Math"] + integer + + + Geography + Geography + dataSetRow["Geography"] + integer + + + History + History + dataSetRow["History"] + integer + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + Student + + + + + Math + + + + + Geography + + + + + History + + + + +
+ + + + + + +
+
+
+
+
+ +
diff --git a/spring-boot-mvc-birt/reports/data.csv b/spring-boot-mvc-birt/reports/data.csv new file mode 100644 index 0000000000..d05e58415e --- /dev/null +++ b/spring-boot-mvc-birt/reports/data.csv @@ -0,0 +1,4 @@ +Student, Math, Geography, History +Bill, 10,3,8 +Tom, 5,6,5 +Anne, 7, 4,9 \ No newline at end of file diff --git a/spring-boot-mvc-birt/reports/static_report.rptdesign b/spring-boot-mvc-birt/reports/static_report.rptdesign new file mode 100644 index 0000000000..d96ff76856 --- /dev/null +++ b/spring-boot-mvc-birt/reports/static_report.rptdesign @@ -0,0 +1,27 @@ + + + Sample Report + + + + + + 100% + + + + + + url + "https://www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png" + + + + + + + + + diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java new file mode 100644 index 0000000000..f1e1619a58 --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java @@ -0,0 +1,93 @@ +package com.baeldung.birt.designer; + +import com.ibm.icu.util.ULocale; +import org.apache.log4j.Logger; +import org.eclipse.birt.core.exception.BirtException; +import org.eclipse.birt.core.framework.Platform; +import org.eclipse.birt.report.model.api.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +import java.io.File; +import java.io.IOException; + +@SpringBootApplication +public class ReportDesignApplication implements CommandLineRunner { + + private static final Logger log = Logger.getLogger(ReportDesignApplication.class); + + @Value("${reports.relative.path}") + private String REPORTS_FOLDER; + + public static void main(String[] args) { + new SpringApplicationBuilder(ReportDesignApplication.class).web(WebApplicationType.NONE).build().run(args); + } + + @Override public void run(String... args) throws Exception { + buildReport(); + } + + private void buildReport() throws IOException, BirtException { + final DesignConfig config = new DesignConfig(); + + final IDesignEngine engine; + try { + Platform.startup(config); + IDesignEngineFactory factory = (IDesignEngineFactory) Platform + .createFactoryObject(IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY); + engine = factory.createDesignEngine(config); + + } catch (Exception ex) { + log.error("Exception during creation of DesignEngine", ex); + throw ex; + } + + SessionHandle session = engine.newSessionHandle(ULocale.ENGLISH); + + ReportDesignHandle design = session.createDesign(); + design.setTitle("Sample Report"); + + // The element factory creates instances of the various BIRT elements. + ElementFactory factory = design.getElementFactory(); + + // Create a simple master page that describes how the report will + // appear when printed. + // + // Note: The report will fail to load in the BIRT designer + // unless you create a master page. + + DesignElementHandle element = factory.newSimpleMasterPage("Page Master"); //$NON-NLS-1$ + design.getMasterPages().add(element); + + // Create a grid + GridHandle grid = factory.newGridItem(null, 2 /* cols */, 1 /* row */); + design.getBody().add(grid); + grid.setWidth("100%"); + + RowHandle row0 = (RowHandle) grid.getRows().get(0); + + // Create an image and add it to the first cell. + ImageHandle image = factory.newImage(null); + CellHandle cell = (CellHandle) row0.getCells().get(0); + cell.getContent().add(image); + image.setURL("\"https://www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png\""); + + // Create a label and add it to the second cell. + LabelHandle label = factory.newLabel(null); + cell = (CellHandle) row0.getCells().get(1); + cell.getContent().add(label); + label.setText("Hello, Baeldung world!"); + + // Save the design and close it. + File report = new File(REPORTS_FOLDER); + report.mkdirs(); + + design.saveAs(new File(report, "static_report.rptdesign").getAbsolutePath()); + design.close(); + log.info("Report generated"); + } + +} diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java new file mode 100644 index 0000000000..6d72017c9d --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java @@ -0,0 +1,29 @@ +package com.baeldung.birt.engine; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@SpringBootApplication +@EnableWebMvc +public class ReportEngineApplication implements WebMvcConfigurer { + @Value("${reports.relative.path}") + private String reportsPath; + @Value("${images.relative.path}") + private String imagesPath; + + public static void main(final String[] args) { + SpringApplication.run(ReportEngineApplication.class, args); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry + .addResourceHandler(reportsPath + imagesPath + "/**") + .addResourceLocations("file:///" + System.getProperty("user.dir") + "/" + reportsPath + imagesPath); + } + +} \ No newline at end of file diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java new file mode 100644 index 0000000000..e2405d02ec --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java @@ -0,0 +1,51 @@ +package com.baeldung.birt.engine.controller; + +import com.baeldung.birt.engine.dto.OutputType; +import com.baeldung.birt.engine.dto.Report; +import com.baeldung.birt.engine.service.BirtReportService; +import org.apache.log4j.Logger; +import org.eclipse.birt.report.engine.api.EngineException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Controller +public class BirtReportController { + private static final Logger log = Logger.getLogger(BirtReportController.class); + + @Autowired + private BirtReportService reportService; + + @RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "/report") + @ResponseBody + public List listReports() { + return reportService.getReports(); + } + + @RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "/report/reload") + @ResponseBody + public ResponseEntity reloadReports(HttpServletResponse response) { + try { + log.info("Reloading reports"); + reportService.loadReports(); + } catch (EngineException e) { + log.error("There was an error reloading the reports in memory: ", e); + return ResponseEntity.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).build(); + } + return ResponseEntity.ok().build(); + } + + @RequestMapping(method = RequestMethod.GET, value = "/report/{name}") + @ResponseBody + public void generateFullReport(HttpServletResponse response, HttpServletRequest request, + @PathVariable("name") String name, @RequestParam("output") String output) { + log.info("Generating full report: " + name + "; format: " + output); + OutputType format = OutputType.from(output); + reportService.generateMainReport(name, format, response, request); + } +} diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java new file mode 100644 index 0000000000..3180a347ba --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java @@ -0,0 +1,21 @@ +package com.baeldung.birt.engine.dto; + +import org.eclipse.birt.report.engine.api.IRenderOption; + +public enum OutputType { + HTML(IRenderOption.OUTPUT_FORMAT_HTML), + PDF(IRenderOption.OUTPUT_FORMAT_PDF), + INVALID("invalid"); + + String val; + OutputType(String val) { + this.val = val; + } + + public static OutputType from(String text) { + for (OutputType output : values()) { + if(output.val.equalsIgnoreCase(text)) return output; + } + return INVALID; + } +} diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java new file mode 100644 index 0000000000..a2d2444b80 --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java @@ -0,0 +1,37 @@ +package com.baeldung.birt.engine.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * Report DTO class + */ +@Data +@NoArgsConstructor +public class Report { + private String title; + private String name; + private List parameters; + + public Report(String title, String name) { + this.title = title; + this.name = name; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Parameter { + private String title; + private String name; + private ParameterType type; + + } + + public enum ParameterType { + INT, STRING + } +} diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java new file mode 100644 index 0000000000..540bbbb530 --- /dev/null +++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java @@ -0,0 +1,168 @@ +package com.baeldung.birt.engine.service; + +import com.baeldung.birt.engine.dto.OutputType; +import com.baeldung.birt.engine.dto.Report; +import org.eclipse.birt.core.exception.BirtException; +import org.eclipse.birt.core.framework.Platform; +import org.eclipse.birt.report.engine.api.*; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.util.*; + +@Service +public class BirtReportService implements ApplicationContextAware, DisposableBean { + @Value("${reports.relative.path}") + private String reportsPath; + @Value("${images.relative.path}") + private String imagesPath; + + private HTMLServerImageHandler htmlImageHandler = new HTMLServerImageHandler(); + + @Autowired + private ResourceLoader resourceLoader; + @Autowired + private ServletContext servletContext; + + private IReportEngine birtEngine; + private ApplicationContext context; + private String imageFolder; + + private Map reports = new HashMap<>(); + + @SuppressWarnings("unchecked") + @PostConstruct + protected void initialize() throws BirtException { + EngineConfig config = new EngineConfig(); + config.getAppContext().put("spring", this.context); + Platform.startup(config); + IReportEngineFactory factory = (IReportEngineFactory) Platform + .createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY); + birtEngine = factory.createReportEngine(config); + imageFolder = System.getProperty("user.dir") + File.separatorChar + reportsPath + imagesPath; + loadReports(); + } + + @Override + public void setApplicationContext(ApplicationContext context) { + this.context = context; + } + + /** + * Load report files to memory + * + */ + public void loadReports() throws EngineException { + File folder = new File(reportsPath); + for (String file : Objects.requireNonNull(folder.list())) { + if (!file.endsWith(".rptdesign")) { + continue; + } + + reports.put(file.replace(".rptdesign", ""), + birtEngine.openReportDesign(folder.getAbsolutePath() + File.separator + file)); + + } + } + + public List getReports() { + List response = new ArrayList<>(); + for (Map.Entry entry : reports.entrySet()) { + IReportRunnable report = reports.get(entry.getKey()); + IGetParameterDefinitionTask task = birtEngine.createGetParameterDefinitionTask(report); + Report reportItem = new Report(report.getDesignHandle().getProperty("title").toString(), entry.getKey()); + for (Object h : task.getParameterDefns(false)) { + IParameterDefn def = (IParameterDefn) h; + reportItem.getParameters() + .add(new Report.Parameter(def.getPromptText(), def.getName(), getParameterType(def))); + } + response.add(reportItem); + } + return response; + } + + private Report.ParameterType getParameterType(IParameterDefn param) { + if (IParameterDefn.TYPE_INTEGER == param.getDataType()) { + return Report.ParameterType.INT; + } + return Report.ParameterType.STRING; + } + + public void generateMainReport(String reportName, OutputType output, HttpServletResponse response, HttpServletRequest request) { + switch (output) { + case HTML: + generateHTMLReport(reports.get(reportName), response, request); + break; + case PDF: + generatePDFReport(reports.get(reportName), response, request); + break; + default: + throw new IllegalArgumentException("Output type not recognized:" + output); + } + } + + /** + * Generate a report as HTML + */ + @SuppressWarnings("unchecked") + private void generateHTMLReport(IReportRunnable report, HttpServletResponse response, HttpServletRequest request) { + IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report); + response.setContentType(birtEngine.getMIMEType("html")); + IRenderOption options = new RenderOption(); + HTMLRenderOption htmlOptions = new HTMLRenderOption(options); + htmlOptions.setOutputFormat("html"); + htmlOptions.setBaseImageURL("/" + reportsPath + imagesPath); + htmlOptions.setImageDirectory(imageFolder); + htmlOptions.setImageHandler(htmlImageHandler); + runAndRenderTask.setRenderOption(htmlOptions); + runAndRenderTask.getAppContext().put(EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, request); + + try { + htmlOptions.setOutputStream(response.getOutputStream()); + runAndRenderTask.run(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + runAndRenderTask.close(); + } + } + + /** + * Generate a report as PDF + */ + @SuppressWarnings("unchecked") + private void generatePDFReport(IReportRunnable report, HttpServletResponse response, HttpServletRequest request) { + IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report); + response.setContentType(birtEngine.getMIMEType("pdf")); + IRenderOption options = new RenderOption(); + PDFRenderOption pdfRenderOption = new PDFRenderOption(options); + pdfRenderOption.setOutputFormat("pdf"); + runAndRenderTask.setRenderOption(pdfRenderOption); + runAndRenderTask.getAppContext().put(EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, request); + + try { + pdfRenderOption.setOutputStream(response.getOutputStream()); + runAndRenderTask.run(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + runAndRenderTask.close(); + } + } + + @Override + public void destroy() { + birtEngine.destroy(); + Platform.shutdown(); + } +} diff --git a/spring-boot-mvc-birt/src/main/resources/application.properties b/spring-boot-mvc-birt/src/main/resources/application.properties new file mode 100644 index 0000000000..5b015c70b1 --- /dev/null +++ b/spring-boot-mvc-birt/src/main/resources/application.properties @@ -0,0 +1,2 @@ +reports.relative.path=reports/ +images.relative.path=images/ \ No newline at end of file diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index bf32e4fc7c..d5a39cdc9f 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -9,4 +9,6 @@ - [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed) - [A Controller, Service and DAO Example with Spring Boot and JSF](https://www.baeldung.com/jsf-spring-boot-controller-service-dao) - [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) \ No newline at end of file +- [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) diff --git a/spring-boot-mvc/pom.xml b/spring-boot-mvc/pom.xml index b219e53431..fee725847f 100644 --- a/spring-boot-mvc/pom.xml +++ b/spring-boot-mvc/pom.xml @@ -1,66 +1,77 @@ - - 4.0.0 - spring-boot-mvc - jar - spring-boot-mvc - Module For Spring Boot MVC + + 4.0.0 + spring-boot-mvc + spring-boot-mvc + jar + Module For Spring Boot MVC - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 - + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + - + - - org.springframework.boot - spring-boot-starter-web - - - org.apache.tomcat.embed - tomcat-embed-jasper - + + org.springframework.boot + spring-boot-starter-web + + + org.apache.tomcat.embed + tomcat-embed-jasper + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-thymeleaf + - - - org.glassfish - javax.faces - 2.3.7 - - - - org.springframework.boot - spring-boot-starter-test - test - + + + org.glassfish + javax.faces + ${javax.faces.version} + - - - com.rometools - rome - ${rome.version} - + + + org.springframework.boot + spring-boot-starter-test + test + - - - org.hibernate.validator - hibernate-validator - - - javax.validation - validation-api - - - org.springframework.boot - spring-boot-starter-validation - + + + com.rometools + rome + ${rome.version} + - + + + org.hibernate.validator + hibernate-validator + + + javax.validation + validation-api + + + org.springframework.boot + spring-boot-starter-validation + + + io.springfox springfox-swagger2 @@ -72,26 +83,33 @@ ${spring.fox.version} - + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.springbootmvc.SpringBootMvcApplication - JAR - - - - + - - 2.9.2 - - 1.10.0 - com.baeldung.springbootmvc.SpringBootMvcApplication - + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.springbootmvc.SpringBootMvcApplication + JAR + + + + + + + 2.9.2 + + 1.10.0 + 2.3.7 + com.baeldung.springbootmvc.SpringBootMvcApplication + diff --git a/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java new file mode 100644 index 0000000000..c16e784dd2 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java @@ -0,0 +1,12 @@ +package com.baeldung.accessparamsjs; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java new file mode 100644 index 0000000000..8759f1bcd6 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java @@ -0,0 +1,32 @@ +package com.baeldung.accessparamsjs; + +import java.util.Map; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +/** + * Sample rest controller for the tutorial article + * "Access Spring MVC Model object in JavaScript". + * + * @author Andrew Shcherbakov + * + */ +@RestController +public class Controller { + + /** + * Define two model objects (one integer and one string) and pass them to the view. + * + * @param model + * @return + */ + @RequestMapping("/index") + public ModelAndView thymeleafView(Map model) { + model.put("number", 1234); + model.put("message", "Hello from Spring MVC"); + return new ModelAndView("thymeleaf/index"); + } + +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java new file mode 100644 index 0000000000..33cd44331f --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java @@ -0,0 +1,20 @@ +package com.baeldung.scheduling; + +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; + +@Configuration +public class ScheduleJobsByProfile { + + private final static Logger LOG = LoggerFactory.getLogger(ScheduleJobsByProfile.class); + + @Profile("prod") + @Bean + public ScheduledJob scheduledJob() + { + return new ScheduledJob("@Profile"); + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java new file mode 100644 index 0000000000..df7cefcd3c --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java @@ -0,0 +1,21 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; + +public class ScheduledJob { + + private String source; + + public ScheduledJob(String source) { + this.source = source; + } + + private final static Logger LOG = LoggerFactory.getLogger(ScheduledJob.class); + + @Scheduled(fixedDelay = 60000) + public void cleanTempDir() { + LOG.info("Cleaning temp directory via {}", source); + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java new file mode 100644 index 0000000000..b03de61641 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java @@ -0,0 +1,28 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +public class ScheduledJobsWithBoolean { + + private final static Logger LOG = LoggerFactory.getLogger(ScheduledJobsWithBoolean.class); + + @Value("${jobs.enabled:true}") + private boolean isEnabled; + + /** + * A scheduled job controlled via application property. The job always + * executes, but the logic inside is protected by a configurable boolean + * flag. + */ + @Scheduled(fixedDelay = 60000) + public void cleanTempDirectory() { + if(isEnabled) { + LOG.info("Cleaning temp directory via boolean flag"); + } + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java new file mode 100644 index 0000000000..081c8d990a --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java @@ -0,0 +1,20 @@ +package com.baeldung.scheduling; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ScheduledJobsWithConditional +{ + /** + * This uses @ConditionalOnProperty to conditionally create a bean, which itself + * is a scheduled job. + * @return ScheduledJob + */ + @Bean + @ConditionalOnProperty(value = "jobs.enabled", matchIfMissing = true, havingValue = "true") + public ScheduledJob runMyCronTask() { + return new ScheduledJob("@ConditionalOnProperty"); + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java new file mode 100644 index 0000000000..577a01f241 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java @@ -0,0 +1,23 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +public class ScheduledJobsWithExpression +{ + private final static Logger LOG = + LoggerFactory.getLogger(ScheduledJobsWithExpression.class); + + /** + * A scheduled job controlled via application property. The job always + * executes, but the logic inside is protected by a configurable boolean + * flag. + */ + @Scheduled(cron = "${jobs.cronSchedule:-}") + public void cleanTempDirectory() { + LOG.info("Cleaning temp directory via placeholder"); + } +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java new file mode 100644 index 0000000000..913e2137f8 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.scheduling; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class SchedulingApplication { + + public static void main(String[] args) { + SpringApplication.run(SchedulingApplication.class, args); + } + +} + diff --git a/spring-boot-mvc/src/main/resources/application.properties b/spring-boot-mvc/src/main/resources/application.properties index 709574239b..6dab470c84 100644 --- a/spring-boot-mvc/src/main/resources/application.properties +++ b/spring-boot-mvc/src/main/resources/application.properties @@ -1 +1,2 @@ -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.main.allow-bean-definition-overriding=true +spring.thymeleaf.view-names=thymeleaf/* \ No newline at end of file diff --git a/spring-boot-mvc/src/main/resources/templates/thymeleaf/index.html b/spring-boot-mvc/src/main/resources/templates/thymeleaf/index.html new file mode 100644 index 0000000000..4939d0ea50 --- /dev/null +++ b/spring-boot-mvc/src/main/resources/templates/thymeleaf/index.html @@ -0,0 +1,29 @@ + + + +Access Spring MVC params + + + + + + + Number= + +
Message= + +

Data from the external JS file (due to loading order)

+
+
+

Asynchronous loading from external JS file (plain JS)

+
+
+

Asynchronous loading from external JS file (jQuery)

+
+
+ + + diff --git a/spring-boot-mvc/src/main/webapp/js/jquery.js b/spring-boot-mvc/src/main/webapp/js/jquery.js new file mode 100644 index 0000000000..4d9b3a2587 --- /dev/null +++ b/spring-boot-mvc/src/main/webapp/js/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w(" + + + + + +
+
+
+
+
+ + +
+ +
+
+
+
+
+ + + + + + + + +
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 diff --git a/spring-security-openid/pom.xml b/spring-security-openid/pom.xml index 4343996e02..0b5eaf6270 100644 --- a/spring-security-openid/pom.xml +++ b/spring-security-openid/pom.xml @@ -2,10 +2,9 @@ 4.0.0 - spring-security-openid - war spring-security-openid + war Spring OpenID sample project diff --git a/spring-security-react/pom.xml b/spring-security-react/pom.xml index 32817945be..c7b7c85be8 100644 --- a/spring-security-react/pom.xml +++ b/spring-security-react/pom.xml @@ -3,7 +3,6 @@ 4.0.0 spring-security-react 0.1-SNAPSHOT - spring-security-react war @@ -73,7 +72,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -168,10 +167,6 @@ 4.3.6.RELEASE 4.2.1.RELEASE - - 3.1.0 - 1.2 - 19.0 3.5 diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md index f92fcfe36b..b905824161 100644 --- a/spring-security-rest-basic-auth/README.md +++ b/spring-security-rest-basic-auth/README.md @@ -6,8 +6,6 @@ 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) -- [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) +- [Basic Authentication with the RestTemplate](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) +- [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) diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml index 61a144db0c..8a90247386 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} @@ -142,7 +142,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -272,12 +272,8 @@ - 4.4.5 - 4.5.3 - - - 1.2 - 3.1.0 + 4.4.11 + 4.5.8 19.0 diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java index 5e15648e9b..3ed0bc82b7 100644 --- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java @@ -4,7 +4,7 @@ import org.apache.http.HttpHost; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.support.BasicAuthorizationInterceptor; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @@ -38,7 +38,7 @@ public class RestTemplateFactory implements FactoryBean, Initializ HttpHost host = new HttpHost("localhost", 8082, "http"); final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host); restTemplate = new RestTemplate(requestFactory); - restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user1", "user1Pass")); + restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass")); } } \ No newline at end of file diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java index 2305a7b6c2..5876e1307b 100644 --- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java @@ -8,7 +8,6 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration @EnableWebMvc diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 6cf624c179..31b3f2be87 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -6,7 +6,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "/WebSecurityConfig.xml" }) +@ContextConfiguration({ "/webSecurityConfig.xml" }) public class SpringContextIntegrationTest { @Test diff --git a/spring-security-rest-custom/README.md b/spring-security-rest-custom/README.md index 85f2b7532c..d7cb31e784 100644 --- a/spring-security-rest-custom/README.md +++ b/spring-security-rest-custom/README.md @@ -8,3 +8,4 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Authentication Provider](http://www.baeldung.com/spring-security-authentication-provider) - [Retrieve User Information in Spring Security](http://www.baeldung.com/get-user-in-spring-security) +- [Spring Security – Run-As Authentication](https://www.baeldung.com/spring-security-run-as-auth) diff --git a/spring-security-rest-custom/pom.xml b/spring-security-rest-custom/pom.xml index 66ad087bf6..2180b917e5 100644 --- a/spring-security-rest-custom/pom.xml +++ b/spring-security-rest-custom/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - com.baeldung spring-security-rest-custom 0.1-SNAPSHOT @@ -9,10 +8,10 @@ war - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -27,6 +26,14 @@ org.springframework.security spring-security-config + + org.thymeleaf.extras + thymeleaf-extras-springsecurity5 + + + org.thymeleaf + thymeleaf-spring5 + diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/config/child/MethodSecurityConfig.java b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/MethodSecurityConfig.java new file mode 100644 index 0000000000..bc9a9f161b --- /dev/null +++ b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/MethodSecurityConfig.java @@ -0,0 +1,37 @@ +package org.baeldung.config.child; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.intercept.RunAsImplAuthenticationProvider; +import org.springframework.security.access.intercept.RunAsManager; +import org.springframework.security.access.intercept.RunAsManagerImpl; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; + + +@Configuration +@EnableGlobalMethodSecurity(securedEnabled = true) +public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { + + @Override + protected RunAsManager runAsManager() { + RunAsManagerImpl runAsManager = new RunAsManagerImpl(); + runAsManager.setKey("MyRunAsKey"); + return runAsManager; + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(runAsAuthenticationProvider()); + } + + @Bean + public AuthenticationProvider runAsAuthenticationProvider() { + RunAsImplAuthenticationProvider authProvider = new RunAsImplAuthenticationProvider(); + authProvider.setKey("MyRunAsKey"); + return authProvider; + } +} \ No newline at end of file diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java index 0c2042f711..7cbbcf31fa 100644 --- a/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java +++ b/spring-security-rest-custom/src/main/java/org/baeldung/config/child/WebConfig.java @@ -2,21 +2,34 @@ package org.baeldung.config.child; import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; +import org.thymeleaf.spring5.ISpringTemplateEngine; +import org.thymeleaf.spring5.SpringTemplateEngine; +import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.spring5.view.ThymeleafViewResolver; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ITemplateResolver; @Configuration @EnableWebMvc @ComponentScan("org.baeldung.web") -// @ImportResource({ "classpath:prop.xml" }) -// @PropertySource("classpath:foo.properties") -public class WebConfig extends WebMvcConfigurerAdapter { +//@ImportResource({ "classpath:prop.xml" }) +//@PropertySource("classpath:foo.properties") +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private ApplicationContext applicationContext; public WebConfig() { super(); @@ -26,7 +39,6 @@ public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(final List> converters) { - super.configureMessageConverters(converters); converters.add(new MappingJackson2HttpMessageConverter()); } @@ -38,5 +50,31 @@ public class WebConfig extends WebMvcConfigurerAdapter { ppc.setIgnoreUnresolvablePlaceholders(true); return ppc; } + + @Bean + public ViewResolver viewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine()); + resolver.setCharacterEncoding("UTF-8"); + return resolver; + } + + @Bean + public ISpringTemplateEngine templateEngine() { + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.setEnableSpringELCompiler(true); + engine.setTemplateResolver(templateResolver()); + engine.addDialect(new SpringSecurityDialect()); + return engine; + } + + private ITemplateResolver templateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/templates/"); + resolver.setSuffix(".html"); + resolver.setTemplateMode(TemplateMode.HTML); + return resolver; + } } \ No newline at end of file diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java b/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java index 616c2a7684..fb3880a33f 100644 --- a/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java +++ b/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java @@ -10,7 +10,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration -// @ImportResource({ "classpath:webSecurityConfig.xml" }) +//@ImportResource({ "classpath:webSecurityConfig.xml" }) @EnableWebSecurity @ComponentScan("org.baeldung.security") public class SecurityConfig extends WebSecurityConfigurerAdapter { diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/service/RunAsService.java b/spring-security-rest-custom/src/main/java/org/baeldung/service/RunAsService.java new file mode 100644 index 0000000000..a6320f8b81 --- /dev/null +++ b/spring-security-rest-custom/src/main/java/org/baeldung/service/RunAsService.java @@ -0,0 +1,17 @@ +package org.baeldung.service; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +@Service +public class RunAsService { + + @Secured({ "ROLE_RUN_AS_REPORTER" }) + public Authentication getCurrentUser() { + Authentication authentication = + SecurityContextHolder.getContext().getAuthentication(); + return authentication; + } +} \ No newline at end of file diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/RunAsController.java b/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/RunAsController.java new file mode 100644 index 0000000000..08f39aa5f2 --- /dev/null +++ b/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/RunAsController.java @@ -0,0 +1,23 @@ +package org.baeldung.web.controller; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + + +@Controller +@RequestMapping("/runas") +public class RunAsController { + + @Secured({ "ROLE_USER", "RUN_AS_REPORTER" }) + @RequestMapping + @ResponseBody + public String tryRunAs() { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + return "Current User Authorities inside this RunAS method only " + + auth.getAuthorities().toString(); + } +} diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/ViewController.java b/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/ViewController.java new file mode 100644 index 0000000000..fbcb9b979e --- /dev/null +++ b/spring-security-rest-custom/src/main/java/org/baeldung/web/controller/ViewController.java @@ -0,0 +1,18 @@ +package org.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ViewController { + + @RequestMapping({ "/index", "/" }) + public String index() { + return "index"; + } + + @RequestMapping({ "/runashome" }) + public String run() { + return "runas"; + } +} diff --git a/spring-security-rest-custom/src/main/resources/prop.xml b/spring-security-rest-custom/src/main/resources/prop.xml index b853d939d6..edaecde655 100644 --- a/spring-security-rest-custom/src/main/resources/prop.xml +++ b/spring-security-rest-custom/src/main/resources/prop.xml @@ -4,9 +4,9 @@ xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-4.2.xsd + http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-4.2.xsd"> + http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/spring-security-rest-custom/src/main/resources/webSecurityConfig.xml b/spring-security-rest-custom/src/main/resources/webSecurityConfig.xml index fa5dc894bf..790b1b1716 100644 --- a/spring-security-rest-custom/src/main/resources/webSecurityConfig.xml +++ b/spring-security-rest-custom/src/main/resources/webSecurityConfig.xml @@ -2,9 +2,9 @@ diff --git a/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/index.html b/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/index.html new file mode 100644 index 0000000000..31cb66ae0a --- /dev/null +++ b/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/index.html @@ -0,0 +1,7 @@ + + + +
Authenticated as
+ + \ No newline at end of file diff --git a/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/runas.html b/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/runas.html new file mode 100644 index 0000000000..c7c3b2e0e4 --- /dev/null +++ b/spring-security-rest-custom/src/main/webapp/WEB-INF/templates/runas.html @@ -0,0 +1,23 @@ + + + + Current user authorities: + user +
+ + Generate Report As Super User + + + + + \ No newline at end of file diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md index c396948a59..f450a514b2 100644 --- a/spring-security-rest/README.md +++ b/spring-security-rest/README.md @@ -11,9 +11,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Spring REST Service Security](http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/) - [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) - [Custom Error Message Handling for REST API](http://www.baeldung.com/global-error-handler-in-a-spring-rest-api) -- [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial) - [Spring Security Context Propagation with @Async](http://www.baeldung.com/spring-security-async-principal-propagation) - [Servlet 3 Async Support with Spring MVC and Spring Security](http://www.baeldung.com/spring-mvc-async-security) - [Intro to Spring Security Expressions](http://www.baeldung.com/spring-security-expressions) -- [Error Handling for REST with Spring](https://www.baeldung.com/exception-handling-for-rest-with-spring) - [Spring Security for a REST API](http://www.baeldung.com/securing-a-restful-web-service-with-spring-security) diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index ef16f2201b..af38c1ffef 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} @@ -84,13 +84,6 @@ ${spring.version} - - - org.springframework.hateoas - spring-hateoas - ${org.springframework.hateoas.version} - - @@ -144,7 +137,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -273,15 +266,8 @@ - - 5.1.0.RELEASE - 0.25.0.RELEASE - - 3.1.0 1.1.0.Final - 1.2 - 2.9.2 26.0-jre diff --git a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java index 0a53da674a..86beeb46a9 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java @@ -29,7 +29,7 @@ public class FooLiveTest { // } // return RestAssured.given().cookie("JSESSIONID", cookie); return RestAssured.given() - .auth() + .auth().preemptive() .basic("user", "userPass"); } diff --git a/spring-security-sso/README.md b/spring-security-sso/README.md index 11b5f011d5..88e3fbb2f7 100644 --- a/spring-security-sso/README.md +++ b/spring-security-sso/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: -- [Simple Single Sign On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2) +- [Simple Single Sign-On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2) +- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration) diff --git a/spring-security-sso/pom.xml b/spring-security-sso/pom.xml index 4b297a91b5..ed8ad87a62 100644 --- a/spring-security-sso/pom.xml +++ b/spring-security-sso/pom.xml @@ -4,7 +4,6 @@ org.baeldung spring-security-sso 1.0.0-SNAPSHOT - spring-security-sso pom @@ -19,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-auth-server/pom.xml b/spring-security-sso/spring-security-sso-auth-server/pom.xml index ff76f377c6..3c8f04a056 100644 --- a/spring-security-sso/spring-security-sso-auth-server/pom.xml +++ b/spring-security-sso/spring-security-sso-auth-server/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-security-sso-auth-server spring-security-sso-auth-server war @@ -13,12 +12,10 @@ - org.springframework.boot spring-boot-starter-web - org.springframework.security.oauth spring-security-oauth2 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"); + } +} 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/README.md b/spring-security-sso/spring-security-sso-kerberos/README.md new file mode 100644 index 0000000000..0227d9ac70 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos) +- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration) 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..9fb86e7658 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java @@ -0,0 +1,22 @@ +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"); + // disable usage of local kerberos ticket cache + System.setProperty("http.use.global.creds", "false"); + } + + 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/SampleClient.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleClient.java new file mode 100644 index 0000000000..745193e3b0 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleClient.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 SampleClient { + + @Value("${app.access-url}") + private String endpoint; + + private RestTemplate restTemplate; + + public SampleClient(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/SampleClientManualTest.java b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleClientManualTest.java new file mode 100644 index 0000000000..fdb1b12531 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleClientManualTest.java @@ -0,0 +1,39 @@ +package kerberos.client; + +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.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) +public class SampleClientManualTest { + + @Autowired + private SampleClient sampleClient; + + @Test + public void givenKerberizedRestTemplate_whenServiceCall_thenSuccess() { + assertEquals("data from kerberized server", sampleClient.getData()); + } + + @Test + public void givenRestTemplate_whenServiceCall_thenFail() { + sampleClient.setRestTemplate(new RestTemplate()); + assertThrows(RestClientException.class, sampleClient::getData); + } +} \ No newline at end of file diff --git a/spring-security-sso/spring-security-sso-ui-2/pom.xml b/spring-security-sso/spring-security-sso-ui-2/pom.xml index e4ccb82fea..a6cf5e5386 100644 --- a/spring-security-sso/spring-security-sso-ui-2/pom.xml +++ b/spring-security-sso/spring-security-sso-ui-2/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-security-sso-ui-2 spring-security-sso-ui-2 war diff --git a/spring-security-sso/spring-security-sso-ui/pom.xml b/spring-security-sso/spring-security-sso-ui/pom.xml index a946db4c3b..7edcee82c8 100644 --- a/spring-security-sso/spring-security-sso-ui/pom.xml +++ b/spring-security-sso/spring-security-sso-ui/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-security-sso-ui spring-security-sso-ui war diff --git a/spring-security-stormpath/pom.xml b/spring-security-stormpath/pom.xml index 5c5783eec5..6db4b38d80 100644 --- a/spring-security-stormpath/pom.xml +++ b/spring-security-stormpath/pom.xml @@ -3,10 +3,11 @@ 4.0.0 com.baeldung spring-security-stormpath - war 1.0-SNAPSHOT spring-security-stormpath + war http://maven.apache.org + abhinabkanrar@gmail.com @@ -31,18 +32,10 @@ com.stormpath.spring stormpath-default-spring-boot-starter - 1.5.4 + ${stormpath-spring.version}
- - - spring-releases - Spring Releases - https://repo.spring.io/libs-release - - - spring-security-stormpath @@ -67,5 +60,9 @@ + + + 1.5.4 +
diff --git a/spring-security-thymeleaf/README.MD b/spring-security-thymeleaf/README.MD index c5deeb9946..36007bce62 100644 --- a/spring-security-thymeleaf/README.MD +++ b/spring-security-thymeleaf/README.MD @@ -4,4 +4,3 @@ Jira BAEL-1556 ### Relevant Articles: - [Spring Security with Thymeleaf](http://www.baeldung.com/spring-security-thymeleaf) -- [Working with Select and Option in Thymeleaf](http://www.baeldung.com/thymeleaf-select-option) diff --git a/spring-security-thymeleaf/pom.xml b/spring-security-thymeleaf/pom.xml index d8b476683a..732eb1dc1d 100644 --- a/spring-security-thymeleaf/pom.xml +++ b/spring-security-thymeleaf/pom.xml @@ -2,12 +2,11 @@ 4.0.0 - com.baeldung spring-security-thymeleaf 0.0.1-SNAPSHOT - jar spring-security-thymeleaf + jar Spring Security with Thymeleaf tutorial diff --git a/spring-security-x509/keystore/Makefile b/spring-security-x509/keystore/Makefile index 63498fea76..2cd7c55c5b 100644 --- a/spring-security-x509/keystore/Makefile +++ b/spring-security-x509/keystore/Makefile @@ -2,6 +2,7 @@ PASSWORD=changeit KEYSTORE=keystore.jks HOSTNAME=localhost CLIENTNAME=cid +CLIENT_PRIVATE_KEY="${CLIENTNAME}_pk" # CN = Common Name # OU = Organization Unit @@ -20,68 +21,71 @@ all: clean create-keystore add-host create-truststore add-client create-keystore: # Generate a certificate authority (CA) - keytool -genkey -alias ca -ext BC=ca:true \ + keytool -genkey -alias ca -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ -validity 3650 -dname $(DNAME_CA) \ -keystore $(KEYSTORE) -storepass $(PASSWORD) add-host: # Generate a host certificate - keytool -genkey -alias $(HOSTNAME) \ + keytool -genkey -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ -validity 3650 -dname $(DNAME_HOST) \ -keystore $(KEYSTORE) -storepass $(PASSWORD) # Generate a host certificate signing request - keytool -certreq -alias $(HOSTNAME) -ext BC=ca:true \ + keytool -certreq -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ -validity 3650 -file "$(HOSTNAME).csr" \ -keystore $(KEYSTORE) -storepass $(PASSWORD) # Generate signed certificate with the certificate authority - keytool -gencert -alias ca \ + keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \ -validity 3650 -sigalg SHA512withRSA \ -infile "$(HOSTNAME).csr" -outfile "$(HOSTNAME).crt" -rfc \ -keystore $(KEYSTORE) -storepass $(PASSWORD) # Import signed certificate into the keystore - keytool -import -trustcacerts -alias $(HOSTNAME) \ + keytool -import -trustcacerts -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ -file "$(HOSTNAME).crt" \ -keystore $(KEYSTORE) -storepass $(PASSWORD) export-authority: # Export certificate authority - keytool -export -alias ca -file ca.crt -rfc \ + keytool -export -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt -rfc \ -keystore $(KEYSTORE) -storepass $(PASSWORD) create-truststore: export-authority # Import certificate authority into a new truststore - keytool -import -trustcacerts -noprompt -alias ca -file ca.crt \ + keytool -import -trustcacerts -noprompt -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) add-client: # Generate client certificate - keytool -genkey -alias $(CLIENTNAME) \ + keytool -genkey -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ -validity 3650 -dname $(DNAME_CLIENT) \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) # Generate a host certificate signing request - keytool -certreq -alias $(CLIENTNAME) -ext BC=ca:true \ + keytool -certreq -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ -validity 3650 -file "$(CLIENTNAME).csr" \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) # Generate signed certificate with the certificate authority - keytool -gencert -alias ca \ + keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \ -validity 3650 -sigalg SHA512withRSA \ -infile "$(CLIENTNAME).csr" -outfile "$(CLIENTNAME).crt" -rfc \ -keystore $(KEYSTORE) -storepass $(PASSWORD) # Import signed certificate into the truststore - keytool -import -trustcacerts -alias $(CLIENTNAME) \ + keytool -import -trustcacerts -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ -file "$(CLIENTNAME).crt" \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) # Export private certificate for importing into a browser - keytool -importkeystore -srcalias $(CLIENTNAME) \ + keytool -importkeystore -srcalias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ -srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \ -destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \ -deststoretype PKCS12 + # Delete client private key as truststore should not contain any private keys + keytool -delete -alias $(CLIENT_PRIVATE_KEY) \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) clean: # Remove generated artifacts diff --git a/spring-security-x509/pom.xml b/spring-security-x509/pom.xml index 658840e866..db7def0c02 100644 --- a/spring-security-x509/pom.xml +++ b/spring-security-x509/pom.xml @@ -5,8 +5,8 @@ com.baeldung spring-security-x509 0.0.1-SNAPSHOT - pom spring-security-x509 + pom parent-boot-1 diff --git a/spring-security-x509/spring-security-x509-basic-auth/pom.xml b/spring-security-x509/spring-security-x509-basic-auth/pom.xml index 5b68a8e63b..0bbd5d3d3d 100644 --- a/spring-security-x509/spring-security-x509-basic-auth/pom.xml +++ b/spring-security-x509/spring-security-x509-basic-auth/pom.xml @@ -4,8 +4,8 @@ 4.0.0 spring-security-x509-basic-auth 0.0.1-SNAPSHOT - jar spring-security-x509-basic-auth + jar Spring x.509 Authentication Demo diff --git a/spring-security-x509/spring-security-x509-client-auth/pom.xml b/spring-security-x509/spring-security-x509-client-auth/pom.xml index 47ec7f971d..3e2e18223a 100644 --- a/spring-security-x509/spring-security-x509-client-auth/pom.xml +++ b/spring-security-x509/spring-security-x509-client-auth/pom.xml @@ -4,8 +4,8 @@ 4.0.0 spring-security-x509-client-auth 0.0.1-SNAPSHOT - jar spring-security-x509-client-auth + jar Spring x.509 Client Authentication Demo diff --git a/spring-session/README.md b/spring-session/README.md index 505d043e75..c9875beadf 100644 --- a/spring-session/README.md +++ b/spring-session/README.md @@ -5,3 +5,4 @@ ### Relevant Articles: - [Guide to Spring Session](https://www.baeldung.com/spring-session) - [Spring Session with JDBC](https://www.baeldung.com/spring-session-jdbc) +- [Spring Session with MongoDB](https://www.baeldung.com/spring-session-mongodb) diff --git a/spring-session/pom.xml b/spring-session/pom.xml index 28dde40272..639686c8ee 100644 --- a/spring-session/pom.xml +++ b/spring-session/pom.xml @@ -4,7 +4,6 @@ org.baeldung spring-session 1.0.0-SNAPSHOT - spring-session pom @@ -18,6 +17,7 @@ spring-session-jdbc spring-session-redis + spring-session-mongodb \ No newline at end of file diff --git a/spring-session/spring-session-jdbc/README.MD b/spring-session/spring-session-jdbc/README.md similarity index 55% rename from spring-session/spring-session-jdbc/README.MD rename to 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) diff --git a/spring-session/spring-session-jdbc/pom.xml b/spring-session/spring-session-jdbc/pom.xml index ce6b5f5908..432715bc0e 100644 --- a/spring-session/spring-session-jdbc/pom.xml +++ b/spring-session/spring-session-jdbc/pom.xml @@ -6,14 +6,10 @@ com.baeldung spring-session-jdbc 0.0.1-SNAPSHOT - jar spring-session-jdbc + jar Spring Session with JDBC tutorial - - 1.4.197 - - parent-boot-2 com.baeldung @@ -52,5 +48,4 @@ -
\ No newline at end of file diff --git a/spring-session/spring-session-mongodb/README.md b/spring-session/spring-session-mongodb/README.md new file mode 100644 index 0000000000..ab42e8d120 --- /dev/null +++ b/spring-session/spring-session-mongodb/README.md @@ -0,0 +1,4 @@ +This module is for Spring Session with MONGO DB tutorial. +Jira BAEL-2886 + +### Relevant Articles: diff --git a/spring-session/spring-session-mongodb/pom.xml b/spring-session/spring-session-mongodb/pom.xml new file mode 100644 index 0000000000..dc055ff32d --- /dev/null +++ b/spring-session/spring-session-mongodb/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + com.baeldung + spring-session-mongodb + 0.0.1-SNAPSHOT + spring-session-mongodb + jar + Spring Session with MongoDB tutorial + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.session + spring-session-data-mongodb + ${spring-session-data-mongodb.version} + + + + org.springframework.boot + spring-boot-starter-data-mongodb + ${spring-boot-starter-data-mongodb.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 2.1.3.RELEASE + 2.1.5.RELEASE + + + \ No newline at end of file diff --git a/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java b/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java new file mode 100644 index 0000000000..2994efc719 --- /dev/null +++ b/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.springsessionmongodb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSessionMongoDBApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringSessionMongoDBApplication.class, args); + } +} diff --git a/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java b/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java new file mode 100644 index 0000000000..b5cb4520a0 --- /dev/null +++ b/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java @@ -0,0 +1,28 @@ +package com.baeldung.springsessionmongodb.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpSession; + +@RestController +public class SpringSessionMongoDBController { + + @GetMapping("/") + public ResponseEntity count(HttpSession session) { + + Integer counter = (Integer) session.getAttribute("count"); + + if (counter == null) { + counter = 1; + } else { + counter++; + } + + session.setAttribute("count", counter); + + return ResponseEntity.ok(counter); + } + +} \ No newline at end of file diff --git a/spring-session/spring-session-mongodb/src/main/resources/application.properties b/spring-session/spring-session-mongodb/src/main/resources/application.properties new file mode 100644 index 0000000000..1b1a6cfbcb --- /dev/null +++ b/spring-session/spring-session-mongodb/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.session.store-type=mongodb +server.port=8080 + +spring.data.mongodb.host=localhost +spring.data.mongodb.port=27017 +spring.data.mongodb.database=springboot-mongo \ No newline at end of file diff --git a/spring-session/spring-session-mongodb/src/main/resources/logback.xml b/spring-session/spring-session-mongodb/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-session/spring-session-mongodb/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-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java b/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java new file mode 100644 index 0000000000..9dc45c5b32 --- /dev/null +++ b/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.springsessionmongodb; + +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.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.session.data.mongo.MongoOperationsSessionRepository; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Base64; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class SpringSessionMongoDBIntegrationTest { + + @Autowired + private MongoOperationsSessionRepository repository; + + private TestRestTemplate restTemplate = new TestRestTemplate(); + + @Test + public void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() { + HttpEntity response = restTemplate + .exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class); + HttpHeaders headers = response.getHeaders(); + String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE); + + Assert.assertEquals(response.getBody(), + repository.findById(getSessionId(set_cookie)).getAttribute("count").toString()); + } + + private String getSessionId(String cookie) { + return new String(Base64.getDecoder().decode(cookie.split(";")[0].split("=")[1])); + } + +} diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-session/spring-session-mongodb/src/test/java/org/baeldung/SpringContextIntegrationTest.java similarity index 72% rename from spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to spring-session/spring-session-mongodb/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 1e2db33395..16b7404f57 100644 --- a/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-session/spring-session-mongodb/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -1,14 +1,13 @@ package org.baeldung; +import com.baeldung.springsessionmongodb.SpringSessionMongoDBApplication; 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.bootstrap.discovery.DiscoveryApplication; - @RunWith(SpringRunner.class) -@SpringBootTest(classes = DiscoveryApplication.class) +@SpringBootTest(classes = SpringSessionMongoDBApplication.class) public class SpringContextIntegrationTest { @Test diff --git a/spring-session/spring-session-redis/README.md b/spring-session/spring-session-redis/README.md index 0d802a4715..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: -- [Introduction to Spring Session](http://www.baeldung.com/spring-session) diff --git a/spring-sleuth/pom.xml b/spring-sleuth/pom.xml index 5ce9e07858..2387915c79 100644 --- a/spring-sleuth/pom.xml +++ b/spring-sleuth/pom.xml @@ -5,14 +5,14 @@ com.baeldung spring-sleuth 1.0.0-SNAPSHOT + spring-sleuth jar - spring-sleuth - + - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -38,19 +38,8 @@ - - - spring-milestones - Spring Milestones - https://repo.spring.io/libs-milestone - - false - - - - - 2.0.0.M7 + 2.0.2.RELEASE 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 diff --git a/spring-soap/.gitignore b/spring-soap/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/spring-soap/.gitignore @@ -0,0 +1 @@ +/target/ 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) diff --git a/spring-soap/pom.xml b/spring-soap/pom.xml new file mode 100644 index 0000000000..16f19b681f --- /dev/null +++ b/spring-soap/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + spring-soap + spring-soap + 1.0.0 + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-web-services + + + wsdl4j + wsdl4j + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 1.6 + + + xjc + + xjc + + + + + ${project.basedir}/src/main/resources/ + ${project.basedir}/src/main/java + false + + + + + + + + 1.8 + 2.1.2.RELEASE + + + diff --git a/spring-soap/src/main/java/com/baeldung/springsoap/Application.java b/spring-soap/src/main/java/com/baeldung/springsoap/Application.java new file mode 100644 index 0000000000..ad9258447c --- /dev/null +++ b/spring-soap/src/main/java/com/baeldung/springsoap/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.springsoap; + +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/spring-soap/src/main/java/com/baeldung/springsoap/CountryEndpoint.java b/spring-soap/src/main/java/com/baeldung/springsoap/CountryEndpoint.java new file mode 100644 index 0000000000..745131767a --- /dev/null +++ b/spring-soap/src/main/java/com/baeldung/springsoap/CountryEndpoint.java @@ -0,0 +1,30 @@ +package com.baeldung.springsoap; + +import com.baeldung.springsoap.gen.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; + +@Endpoint +public class CountryEndpoint { + + private static final String NAMESPACE_URI = "http://www.baeldung.com/springsoap/gen"; + + private CountryRepository countryRepository; + + @Autowired + public CountryEndpoint(CountryRepository countryRepository) { + this.countryRepository = countryRepository; + } + + @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest") + @ResponsePayload + public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) { + GetCountryResponse response = new GetCountryResponse(); + response.setCountry(countryRepository.findCountry(request.getName())); + + return response; + } +} diff --git a/spring-soap/src/main/java/com/baeldung/springsoap/CountryRepository.java b/spring-soap/src/main/java/com/baeldung/springsoap/CountryRepository.java new file mode 100644 index 0000000000..8a0f58a64e --- /dev/null +++ b/spring-soap/src/main/java/com/baeldung/springsoap/CountryRepository.java @@ -0,0 +1,47 @@ +package com.baeldung.springsoap; + +import com.baeldung.springsoap.gen.*; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.Map; + +@Component +public class CountryRepository { + + private static final Map countries = new HashMap<>(); + + @PostConstruct + public void initData() { + Country spain = new Country(); + spain.setName("Spain"); + spain.setCapital("Madrid"); + spain.setCurrency(Currency.EUR); + spain.setPopulation(46704314); + + countries.put(spain.getName(), spain); + + Country poland = new Country(); + poland.setName("Poland"); + poland.setCapital("Warsaw"); + poland.setCurrency(Currency.PLN); + poland.setPopulation(38186860); + + countries.put(poland.getName(), poland); + + Country uk = new Country(); + uk.setName("United Kingdom"); + uk.setCapital("London"); + uk.setCurrency(Currency.GBP); + uk.setPopulation(63705000); + + countries.put(uk.getName(), uk); + } + + public Country findCountry(String name) { + Assert.notNull(name, "The country's name must not be null"); + return countries.get(name); + } +} diff --git a/spring-soap/src/main/java/com/baeldung/springsoap/WebServiceConfig.java b/spring-soap/src/main/java/com/baeldung/springsoap/WebServiceConfig.java new file mode 100644 index 0000000000..930a961208 --- /dev/null +++ b/spring-soap/src/main/java/com/baeldung/springsoap/WebServiceConfig.java @@ -0,0 +1,41 @@ +package com.baeldung.springsoap; + +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.ws.config.annotation.EnableWs; +import org.springframework.ws.config.annotation.WsConfigurerAdapter; +import org.springframework.ws.transport.http.MessageDispatcherServlet; +import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; +import org.springframework.xml.xsd.SimpleXsdSchema; +import org.springframework.xml.xsd.XsdSchema; + +@EnableWs +@Configuration +public class WebServiceConfig extends WsConfigurerAdapter { + + @Bean + public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { + MessageDispatcherServlet servlet = new MessageDispatcherServlet(); + servlet.setApplicationContext(applicationContext); + servlet.setTransformWsdlLocations(true); + return new ServletRegistrationBean(servlet, "/ws/*"); + } + + @Bean(name = "countries") + public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { + DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); + wsdl11Definition.setPortTypeName("CountriesPort"); + wsdl11Definition.setLocationUri("/ws"); + wsdl11Definition.setTargetNamespace("http://www.baeldung.com/springsoap/gen"); + wsdl11Definition.setSchema(countriesSchema); + return wsdl11Definition; + } + + @Bean + public XsdSchema countriesSchema() { + return new SimpleXsdSchema(new ClassPathResource("countries.xsd")); + } +} diff --git a/spring-soap/src/main/resources/countries.xsd b/spring-soap/src/main/resources/countries.xsd new file mode 100644 index 0000000000..524e5ac2d5 --- /dev/null +++ b/spring-soap/src/main/resources/countries.xsd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-soap/src/test/java/com/baeldung/springsoap/ApplicationIntegrationTest.java b/spring-soap/src/test/java/com/baeldung/springsoap/ApplicationIntegrationTest.java new file mode 100644 index 0000000000..3b071c286f --- /dev/null +++ b/spring-soap/src/test/java/com/baeldung/springsoap/ApplicationIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.springsoap; + +import com.baeldung.springsoap.gen.GetCountryRequest; +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.boot.web.server.LocalServerPort; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.ClassUtils; +import org.springframework.ws.client.core.WebServiceTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class ApplicationIntegrationTest { + + private Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); + + @LocalServerPort private int port = 0; + + @Before + public void init() throws Exception { + marshaller.setPackagesToScan(ClassUtils.getPackageName(GetCountryRequest.class)); + marshaller.afterPropertiesSet(); + } + + @Test + public void whenSendRequest_thenResponseIsNotNull() { + WebServiceTemplate ws = new WebServiceTemplate(marshaller); + GetCountryRequest request = new GetCountryRequest(); + request.setName("Spain"); + + assertThat(ws.marshalSendAndReceive("http://localhost:" + port + "/ws", request)).isNotNull(); + } +} diff --git a/spring-soap/src/test/resources/request.xml b/spring-soap/src/test/resources/request.xml new file mode 100644 index 0000000000..7a94aeeee6 --- /dev/null +++ b/spring-soap/src/test/resources/request.xml @@ -0,0 +1,23 @@ + + + + + Spain + + + + + + + + + + Spain + 46704314 + Madrid + EUR + + + + \ No newline at end of file diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml index 6b7b90443a..e948c908d4 100644 --- a/spring-social-login/pom.xml +++ b/spring-social-login/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-social-login spring-social-login war 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()); diff --git a/spring-static-resources/README.md b/spring-static-resources/README.md index c12e0272d4..64f017b5dd 100644 --- a/spring-static-resources/README.md +++ b/spring-static-resources/README.md @@ -2,3 +2,4 @@ - [Cachable Static Assets with Spring MVC](http://www.baeldung.com/cachable-static-assets-with-spring-mvc) - [Minification of JS and CSS Assets with Maven](http://www.baeldung.com/maven-minification-of-js-and-css-assets) - [Serve Static Resources with Spring](http://www.baeldung.com/spring-mvc-static-resources) +- [Load a Resource as a String in Spring](https://www.baeldung.com/spring-load-resource-as-string) diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index 3ca7783682..84519a37c1 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -5,8 +5,8 @@ com.baeldung spring-static-resources 0.1.0-SNAPSHOT - war spring-static-resources + war com.baeldung @@ -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} @@ -140,6 +140,21 @@ handlebars ${handlebars.version} + + + + commons-io + commons-io + ${commons.io.version} + + + + org.springframework + spring-test + ${spring.version} + test + + @@ -188,25 +203,21 @@ - - 5.0.6.RELEASE - 1.8.9 2.3.2-b02 - - 2.9.6 - 6.0.10.Final 4.1.0 2.10 - 1.2 4.0.1 1 1.5.1 + + + 2.5 \ No newline at end of file diff --git a/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java new file mode 100644 index 0000000000..32b9ba84d0 --- /dev/null +++ b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.loadresourceasstring; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LoadResourceConfig { + + @Bean + public String resourceString() { + return ResourceReader.readFileToString("resource.txt"); + } + +} diff --git a/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java new file mode 100644 index 0000000000..7bc1babe91 --- /dev/null +++ b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java @@ -0,0 +1,30 @@ +package com.baeldung.loadresourceasstring; + +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.FileCopyUtils; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; + +import static java.nio.charset.StandardCharsets.UTF_8; + + +public class ResourceReader { + + public static String readFileToString(String path) { + ResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource resource = resourceLoader.getResource(path); + return asString(resource); + } + + public static String asString(Resource resource) { + try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) { + return FileCopyUtils.copyToString(reader); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java index dbc548e028..7bd03617be 100644 --- a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java @@ -18,7 +18,7 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import org.springframework.web.servlet.resource.GzipResourceResolver; +import org.springframework.web.servlet.resource.EncodedResourceResolver; import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -57,10 +57,10 @@ public class MvcConfig implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { // For examples using Spring 4.1.0 if ((env.getProperty("resource.handler.conf")).equals("4.1.0")) { - registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver()).addResolver(new PathResourceResolver()); + registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver()).addResolver(new PathResourceResolver()); registry.addResourceHandler("/resources/**").addResourceLocations("/resources/", "classpath:/other-resources/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); registry.addResourceHandler("/files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); - registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver()); + registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver()); } // For examples using Spring 4.0.7 else if ((env.getProperty("resource.handler.conf")).equals("4.0.7")) { diff --git a/spring-static-resources/src/main/resources/resource.txt b/spring-static-resources/src/main/resources/resource.txt new file mode 100644 index 0000000000..e78cfa90c2 --- /dev/null +++ b/spring-static-resources/src/main/resources/resource.txt @@ -0,0 +1 @@ +This is a resource text file. This file will be loaded as a resource and use its contents as a string. \ No newline at end of file diff --git a/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..67dc50030c --- /dev/null +++ b/spring-static-resources/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,20 @@ +package com.baeldung; + +import org.baeldung.spring.SecSecurityConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SecSecurityConfig.class }, loader = AnnotationConfigContextLoader.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } +} diff --git a/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java b/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java new file mode 100644 index 0000000000..c16c1a9720 --- /dev/null +++ b/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java @@ -0,0 +1,57 @@ +package com.baeldung.loadresourceasstring; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.util.FileCopyUtils; + +import java.io.InputStreamReader; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = LoadResourceConfig.class) +public class LoadResourceAsStringIntegrationTest { + + private static final String EXPECTED_RESOURCE_VALUE = "This is a resource text file. This file will be loaded as a " + "resource and use its contents as a string."; + + @Value("#{T(com.baeldung.loadresourceasstring.ResourceReader).readFileToString('classpath:resource.txt')}") + private String resourceStringUsingSpel; + + @Autowired + @Qualifier("resourceString") + private String resourceString; + + @Autowired + private ResourceLoader resourceLoader; + + @Test + public void givenUsingResourceLoadAndFileCopyUtils_whenConvertingAResourceToAString_thenCorrect() { + Resource resource = resourceLoader.getResource("classpath:resource.txt"); + assertEquals(EXPECTED_RESOURCE_VALUE, ResourceReader.asString(resource)); + } + + @Test + public void givenUsingResourceStringBean_whenConvertingAResourceToAString_thenCorrect() { + assertEquals(EXPECTED_RESOURCE_VALUE, resourceString); + } + + @Test + public void givenUsingSpel_whenConvertingAResourceToAString_thenCorrect() { + assertEquals(EXPECTED_RESOURCE_VALUE, resourceStringUsingSpel); + } + + + + +} diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml index 06a92ffae7..cfbc90155c 100644 --- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml +++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml @@ -1,12 +1,12 @@ 4.0.0 - spring-swagger-codegen-api-client - jar spring-swagger-codegen-api-client https://github.com/swagger-api/swagger-codegen Swagger Java + jar + scm:git:git@github.com:swagger-api/swagger-codegen.git scm:git:git@github.com:swagger-api/swagger-codegen.git @@ -20,6 +20,7 @@ repo + Swagger @@ -157,27 +158,27 @@ com.fasterxml.jackson.core jackson-core - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.core jackson-annotations - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.datatype jackson-datatype-joda - ${jackson-version} + ${jackson.version} joda-time @@ -189,7 +190,6 @@ 1.5.15 4.3.9.RELEASE - 2.8.9 2.9.9 2.2 1.5 diff --git a/spring-thymeleaf-2/pom.xml b/spring-thymeleaf-2/pom.xml new file mode 100644 index 0000000000..1b95cac43c --- /dev/null +++ b/spring-thymeleaf-2/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + spring-thymeleaf-2 + spring-thymeleaf-2 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + spring-thymeleaf-2 + + + + 1.8 + 1.8 + + diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java new file mode 100644 index 0000000000..2ccca82497 --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java @@ -0,0 +1,11 @@ +package com.baeldung.thymeleaf; + +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/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java new file mode 100644 index 0000000000..9e223d1323 --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java @@ -0,0 +1,22 @@ +package com.baeldung.thymeleaf.enums; + +public enum Color { + BLACK("Black"), + BLUE("Blue"), + RED("Red"), + YELLOW("Yellow"), + GREEN("Green"), + ORANGE("Orange"), + PURPLE("Purple"), + WHITE("White"); + + private final String displayValue; + + private Color(String displayValue) { + this.displayValue = displayValue; + } + + public String getDisplayValue() { + return displayValue; + } +} diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java new file mode 100644 index 0000000000..dc6504c3bc --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java @@ -0,0 +1,27 @@ +package com.baeldung.thymeleaf.enums; + +public class Widget { + private String name; + private Color color; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + @Override + public String toString() { + return "Widget [name=" + name + ", color=" + color + "]"; + } +} diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java new file mode 100644 index 0000000000..c66464d75b --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java @@ -0,0 +1,23 @@ +package com.baeldung.thymeleaf.enums; + +import javax.validation.Valid; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.ui.Model; + +@Controller +public class WidgetController { + @GetMapping("/widget/add") + public String addWidget(@ModelAttribute Widget widget) { + return "enums/new"; + } + + @PostMapping("/widget/add") + public String saveWidget(@Valid Widget widget, Model model) { + model.addAttribute("widget", widget); + return "enums/view"; + } +} diff --git a/spring-thymeleaf-2/src/main/resources/templates/enums/new.html b/spring-thymeleaf-2/src/main/resources/templates/enums/new.html new file mode 100644 index 0000000000..7ac4665171 --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/enums/new.html @@ -0,0 +1,19 @@ + + + + +Enums in Thymeleaf + + +
+

Add New Widget

+ + + + + +
+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/main/resources/templates/enums/view.html b/spring-thymeleaf-2/src/main/resources/templates/enums/view.html new file mode 100644 index 0000000000..f766f66277 --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/enums/view.html @@ -0,0 +1,30 @@ + + + + +Enums in Thymeleaf + + +

View Widget

+
+ + +
+
+ + +
+
+ This color screams danger. +
+
+ Green is for go. +
+
+ Alert + Warning + Caution + All Good +
+ + \ No newline at end of file diff --git a/spring-thymeleaf/README.md b/spring-thymeleaf/README.md index f9e7dd90a7..b6824003db 100644 --- a/spring-thymeleaf/README.md +++ b/spring-thymeleaf/README.md @@ -8,7 +8,7 @@ - [Thymeleaf: Custom Layout Dialect](http://www.baeldung.com/thymeleaf-spring-layouts) - [Spring and Thymeleaf 3: Expressions](http://www.baeldung.com/spring-thymeleaf-3-expressions) - [Spring MVC + Thymeleaf 3.0: New Features](http://www.baeldung.com/spring-thymeleaf-3) -- [How to Work with Dates in Thymeleaef](http://www.baeldung.com/dates-in-thymeleaf) +- [How to Work with Dates in Thymeleaf](http://www.baeldung.com/dates-in-thymeleaf) - [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven) - [Working with Boolean in Thymeleaf](http://www.baeldung.com/thymeleaf-boolean) - [Working with Fragments in Thymeleaf](http://www.baeldung.com/spring-thymeleaf-fragments) diff --git a/spring-thymeleaf/pom.xml b/spring-thymeleaf/pom.xml index 78f95fe1df..cdc2ed25ae 100644 --- a/spring-thymeleaf/pom.xml +++ b/spring-thymeleaf/pom.xml @@ -4,8 +4,8 @@ com.baeldung spring-thymeleaf 0.1-SNAPSHOT - war spring-thymeleaf + war com.baeldung diff --git a/spring-userservice/.gitignore b/spring-userservice/.gitignore new file mode 100644 index 0000000000..afe61e7c0c --- /dev/null +++ b/spring-userservice/.gitignore @@ -0,0 +1 @@ +derby.log \ No newline at end of file diff --git a/spring-userservice/pom.xml b/spring-userservice/pom.xml index e562171103..e6e8553c80 100644 --- a/spring-userservice/pom.xml +++ b/spring-userservice/pom.xml @@ -176,7 +176,7 @@ javax.servlet.jsp.jstl jstl-api - ${jstl-api.version} + ${jstl.version} org.springframework.boot @@ -191,7 +191,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} @@ -225,15 +225,12 @@ 5.2.10.Final 5.1.40 1.10.5.RELEASE - 1.4.193 10.13.1.1 5.3.3.Final 2.2.5 1.1.2 - 1.2 - 3.1.0 19.0 diff --git a/spring-vault/pom.xml b/spring-vault/pom.xml index aad6da1cc3..ccad71c024 100644 --- a/spring-vault/pom.xml +++ b/spring-vault/pom.xml @@ -4,12 +4,11 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - com.baeldung spring-vault 0.0.1-SNAPSHOT - jar spring-vault + jar Spring Vault sample project diff --git a/spring-vertx/pom.xml b/spring-vertx/pom.xml index 14ed77d359..1a0e1c0223 100644 --- a/spring-vertx/pom.xml +++ b/spring-vertx/pom.xml @@ -3,15 +3,15 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-vertx - jar spring-vertx A demo project with vertx spring integration + jar - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/spring-webflux-amqp/pom.xml b/spring-webflux-amqp/pom.xml index 4faa165c50..88f5eff403 100755 --- a/spring-webflux-amqp/pom.xml +++ b/spring-webflux-amqp/pom.xml @@ -1,82 +1,76 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + org.baeldung.spring + spring-webflux-amqp + 1.0.0-SNAPSHOT + spring-webflux-amqp + jar + Spring WebFlux AMQP Sample - org.baeldung.spring - spring-webflux-amqp - 1.0.0-SNAPSHOT - jar - spring-webflux-amqp - Spring WebFlux AMQP Sample + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 - + + + + + org.springframework.boot + spring-boot-dependencies + + 2.1.3.RELEASE + pom + import + + + - - - org.springframework.boot - spring-boot-starter-amqp - - - org.springframework.boot - spring-boot-starter-webflux - + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-starter-webflux + - - org.springframework.boot - spring-boot-configuration-processor - true - + + org.springframework.boot + spring-boot-configuration-processor + true + - - org.springframework.boot - spring-boot-starter-test - test - + + org.springframework.boot + spring-boot-starter-test + test + - - io.projectreactor - reactor-test - test - + + io.projectreactor + reactor-test + test + - - org.springframework.boot - spring-boot-starter-integration - - + + org.springframework.boot + spring-boot-starter-integration + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/libs-snapshot - - true - - - - - - - spring-releases - Spring Releases - https://repo.spring.io/libs-release - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java index 30614e7ee6..8a31299333 100755 --- a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java +++ b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java @@ -3,6 +3,12 @@ package org.baeldung.spring.amqp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.web.filter.reactive.HiddenHttpMethodFilter; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilterChain; + +import reactor.core.publisher.Mono; @SpringBootApplication @EnableConfigurationProperties(DestinationsConfig.class) @@ -12,4 +18,19 @@ public class SpringWebfluxAmqpApplication { SpringApplication.run(SpringWebfluxAmqpApplication.class, args); } + + /** + * This is a workaround for https://github.com/spring-projects/spring-framework/issues/21094 + * @return + */ + @Bean + public HiddenHttpMethodFilter hiddenHttpMethodFilter() { + return new HiddenHttpMethodFilter() { + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + return chain.filter(exchange); + } + }; + } + } diff --git a/spring-webflux-amqp/src/main/resources/application.yml b/spring-webflux-amqp/src/main/resources/application.yml index 702aaba357..3f527ce4c5 100755 --- a/spring-webflux-amqp/src/main/resources/application.yml +++ b/spring-webflux-amqp/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: rabbitmq: - host: localhost + host: 192.168.99.100 port: 5672 username: guest password: guest diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index 266c20adee..fbbbdddbf7 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -1,7 +1,7 @@ - 4.0.0 - com.baeldung spring-zuul 1.0.0-SNAPSHOT @@ -9,10 +9,10 @@ pom - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -38,7 +38,7 @@ - 1.2.7.RELEASE + 2.1.0.RELEASE 3.5 diff --git a/spring-zuul/spring-zuul-foos-resource/pom.xml b/spring-zuul/spring-zuul-foos-resource/pom.xml index 70e39db4aa..4fe4e1dbbc 100644 --- a/spring-zuul/spring-zuul-foos-resource/pom.xml +++ b/spring-zuul/spring-zuul-foos-resource/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-zuul-foos-resource spring-zuul-foos-resource war diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java index 9f1d2e162b..77eabe771b 100644 --- a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java @@ -2,7 +2,7 @@ package org.baeldung.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication public class ResourceServerApplication extends SpringBootServletInitializer { diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java index c040c8ac42..1a45d20edb 100644 --- a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java @@ -3,11 +3,11 @@ package org.baeldung.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc @ComponentScan({ "org.baeldung.web.controller" }) -public class ResourceServerWebConfig extends WebMvcConfigurerAdapter { +public class ResourceServerWebConfig implements WebMvcConfigurer { } diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties index 94c0984ac3..9298027030 100644 --- a/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties +++ b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties @@ -1,2 +1,2 @@ -server.contextPath=/spring-zuul-foos-resource -server.port=8081 \ No newline at end of file +server.servlet.context-path=/spring-zuul-foos-resource +server.port=8081 diff --git a/spring-zuul/spring-zuul-ui/pom.xml b/spring-zuul/spring-zuul-ui/pom.xml index 6090f5f8b8..619e6c6b78 100644 --- a/spring-zuul/spring-zuul-ui/pom.xml +++ b/spring-zuul/spring-zuul-ui/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - spring-zuul-ui spring-zuul-ui war @@ -15,7 +14,7 @@ org.springframework.cloud - spring-cloud-starter-zuul + spring-cloud-starter-netflix-zuul ${spring-cloud.version} diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java index b8eda25960..d3e13639ef 100644 --- a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java +++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java @@ -2,7 +2,7 @@ package org.baeldung.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableZuulProxy diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java index 0732182354..7cda1f0e95 100644 --- a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java +++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java @@ -7,11 +7,11 @@ import org.springframework.web.servlet.config.annotation.DefaultServletHandlerCo import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc -public class UiWebConfig extends WebMvcConfigurerAdapter { +public class UiWebConfig implements WebMvcConfigurer { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { @@ -25,7 +25,6 @@ public class UiWebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); registry.addViewController("/").setViewName("forward:/index"); registry.addViewController("/index"); registry.addViewController("/login"); diff --git a/stripe/pom.xml b/stripe/pom.xml index 1e13612fb5..86c6389f7f 100644 --- a/stripe/pom.xml +++ b/stripe/pom.xml @@ -2,13 +2,12 @@ 4.0.0 - com.baeldung.stripe stripe 0.0.1-SNAPSHOT - jar Stripe Demo project for Stripe API + jar parent-boot-1 @@ -41,7 +40,6 @@ - 1.16.16 4.2.0 diff --git a/struts-2/pom.xml b/struts-2/pom.xml index ac8579d9e0..7de688ff2c 100644 --- a/struts-2/pom.xml +++ b/struts-2/pom.xml @@ -4,8 +4,8 @@ com.baeldung struts-2 0.0.1-SNAPSHOT - pom struts-2 + pom com.baeldung @@ -33,7 +33,7 @@ javax.servlet javax.servlet-api - ${servlet.version} + ${javax.servlet-api.version} org.springframework @@ -69,7 +69,6 @@ 2.5.5 2.5.8 - 3.0.1 4.3.6.RELEASE 3.0.0 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..f826375ac1 --- /dev/null +++ b/tensorflow-java/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Tensorflow for Java](https://www.baeldung.com/tensorflow-java) diff --git a/tensorflow-java/pom.xml b/tensorflow-java/pom.xml new file mode 100644 index 0000000000..f9abde737c --- /dev/null +++ b/tensorflow-java/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + com.baeldung + tensorflow-java + 1.0-SNAPSHOT + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + 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 + + + + + + 1.12.0 + 5.4.0 + + \ 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(); + + } + +} diff --git a/testing-modules/easymock/pom.xml b/testing-modules/easymock/pom.xml new file mode 100644 index 0000000000..2b16dd3a1f --- /dev/null +++ b/testing-modules/easymock/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + com.baeldung + testing-modules + 1.0.0-SNAPSHOT + + easymock + easymock + http://maven.apache.org + + UTF-8 + + + + org.easymock + easymock + 4.0.2 + test + + + diff --git a/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ForecastProcessor.java b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ForecastProcessor.java new file mode 100644 index 0000000000..482e985e5b --- /dev/null +++ b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ForecastProcessor.java @@ -0,0 +1,28 @@ +package com.baeldung.testing.easymock; + +import java.math.BigDecimal; + +public class ForecastProcessor { + private WeatherService weatherService; + + public BigDecimal getMaximumTemperature(String locationName) { + + Location location = new Location(locationName); + + try { + weatherService.populateTemperature(location); + } catch (ServiceUnavailableException e) { + return null; + } + + return location.getMaximumTemparature(); + } + + public WeatherService getWeatherService() { + return weatherService; + } + + public void setWeatherService(WeatherService weatherService) { + this.weatherService = weatherService; + } +} diff --git a/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/Location.java b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/Location.java new file mode 100644 index 0000000000..5f318acd5c --- /dev/null +++ b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/Location.java @@ -0,0 +1,33 @@ +package com.baeldung.testing.easymock; + +import java.math.BigDecimal; + +public class Location { + private String name; + private BigDecimal minimumTemperature; + private BigDecimal maximumTemparature; + + public Location(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public BigDecimal getMinimumTemperature() { + return minimumTemperature; + } + + public void setMinimumTemperature(BigDecimal minimumTemperature) { + this.minimumTemperature = minimumTemperature; + } + + public BigDecimal getMaximumTemparature() { + return maximumTemparature; + } + + public void setMaximumTemparature(BigDecimal maximumTemparature) { + this.maximumTemparature = maximumTemparature; + } +} diff --git a/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ServiceUnavailableException.java b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ServiceUnavailableException.java new file mode 100644 index 0000000000..abab4bdee8 --- /dev/null +++ b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/ServiceUnavailableException.java @@ -0,0 +1,7 @@ +package com.baeldung.testing.easymock; + +public class ServiceUnavailableException extends Exception { + + private static final long serialVersionUID = 6961151537340723535L; + +} diff --git a/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/WeatherService.java b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/WeatherService.java new file mode 100644 index 0000000000..1c6b11b17b --- /dev/null +++ b/testing-modules/easymock/src/main/java/com/baeldung/testing/easymock/WeatherService.java @@ -0,0 +1,5 @@ +package com.baeldung.testing.easymock; + +public interface WeatherService { + void populateTemperature(Location location) throws ServiceUnavailableException; +} diff --git a/testing-modules/easymock/src/test/java/com/baeldung/testing/easymock/ForecastProcessorUnitTest.java b/testing-modules/easymock/src/test/java/com/baeldung/testing/easymock/ForecastProcessorUnitTest.java new file mode 100644 index 0000000000..fa8fa847ae --- /dev/null +++ b/testing-modules/easymock/src/test/java/com/baeldung/testing/easymock/ForecastProcessorUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.testing.easymock; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.math.BigDecimal; + +import org.easymock.EasyMock; +import org.easymock.EasyMockRule; +import org.easymock.Mock; +import org.easymock.TestSubject; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +public class ForecastProcessorUnitTest { + private static int MAX_TEMP = 90; + + @Rule + public EasyMockRule rule = new EasyMockRule(this); + + @TestSubject + private ForecastProcessor forecastProcessor = new ForecastProcessor(); + + @Mock + private WeatherService mockWeatherService; + + @Before + public void setUp() { + forecastProcessor.setWeatherService(mockWeatherService); + } + + @SuppressWarnings("unchecked") + @Test + public void givenLocationName_whenWeatherServicePopulatesTemperatures_thenMaxTempReturned() throws ServiceUnavailableException { + mockWeatherService.populateTemperature(EasyMock.anyObject(Location.class)); + EasyMock.expectLastCall() + .andAnswer(() -> { + Location passedLocation = (Location) EasyMock.getCurrentArguments()[0]; + passedLocation.setMaximumTemparature(new BigDecimal(MAX_TEMP)); + passedLocation.setMinimumTemperature(new BigDecimal(MAX_TEMP - 10)); + return null; + }); + EasyMock.replay(mockWeatherService); + BigDecimal maxTemperature = forecastProcessor.getMaximumTemperature("New York"); + EasyMock.verify(mockWeatherService); + assertThat(maxTemperature, equalTo(new BigDecimal(MAX_TEMP))); + } +} diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml index 158da176c6..e708d939e4 100644 --- a/testing-modules/gatling/pom.xml +++ b/testing-modules/gatling/pom.xml @@ -14,6 +14,31 @@ 1.0.0-SNAPSHOT ../../ + + + + + io.gatling + gatling-app + ${gatling.version} + + + io.gatling + gatling-recorder + ${gatling.version} + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + + + org.scala-lang + scala-library + ${scala.version} + + + @@ -77,52 +102,27 @@ simulation - - io.gatling - gatling-maven-plugin - ${gatling-maven-plugin.version} - - - test - - execute - - - true - - - - - - + + io.gatling + gatling-maven-plugin + ${gatling-maven-plugin.version} + + + test + + execute + + + true + + + + + + - - - - io.gatling - gatling-app - ${gatling.version} - - - io.gatling - gatling-recorder - ${gatling.version} - - - io.gatling.highcharts - gatling-charts-highcharts - ${gatling.version} - - - org.scala-lang - scala-library - ${scala.version} - - - - 1.8 1.8 diff --git a/testing-modules/groovy-spock/.gitignore b/testing-modules/groovy-spock/.gitignore new file mode 100644 index 0000000000..37118ef42c --- /dev/null +++ b/testing-modules/groovy-spock/.gitignore @@ -0,0 +1 @@ +/report-*.json \ No newline at end of file diff --git a/testing-modules/groovy-spock/README.md b/testing-modules/groovy-spock/README.md index 18d26e8fc0..e61c56d470 100644 --- a/testing-modules/groovy-spock/README.md +++ b/testing-modules/groovy-spock/README.md @@ -1,3 +1,5 @@ ### 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) +- [Guide to Spock Extensions](https://www.baeldung.com/spock-extensions) diff --git a/testing-modules/groovy-spock/pom.xml b/testing-modules/groovy-spock/pom.xml index 3dd01c29ab..35d8f5034f 100644 --- a/testing-modules/groovy-spock/pom.xml +++ b/testing-modules/groovy-spock/pom.xml @@ -5,8 +5,8 @@ org.spockframework groovy-spock 1.0-SNAPSHOT - jar groovy-spock + jar com.baeldung @@ -48,9 +48,9 @@ - 1.0-groovy-2.4 + 1.3-groovy-2.4 2.4.7 1.5 - \ No newline at end of file + 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/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/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..9010481220 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy @@ -0,0 +1,22 @@ +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"() { + expect: + true + } + + @IgnoreIf({ os.isWindows() }) + def "I'm using Spock helper classes to run only on windows"() { + expect: + true + } + + +} 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..00fa55e21e --- /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 'stkacktrace'() { +// 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/groovy/mocks/ItemServiceUnitTest.groovy b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceUnitTest.groovy new file mode 100644 index 0000000000..2ccb72f726 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceUnitTest.groovy @@ -0,0 +1,131 @@ +package mocks + +import spock.lang.Specification + +class ItemServiceUnitTest 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') + } + +} 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..4b017aeefc --- /dev/null +++ b/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy @@ -0,0 +1,30 @@ +import extensions.TimeoutTest +import spock.lang.Issue + +runner { + + if (System.getenv("FILTER_STACKTRACE") == null) { + filterStackTrace false + } + + 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') + } + +} diff --git a/testing-modules/junit-5-advanced/pom.xml b/testing-modules/junit-5-advanced/pom.xml new file mode 100644 index 0000000000..f65f7e2a2f --- /dev/null +++ b/testing-modules/junit-5-advanced/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + junit-5-advanced + 1.0-SNAPSHOT + junit-5-advanced + Advanced JUnit 5 Topics + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + + + 5.4.2 + 2.21.0 + + + diff --git a/testing-modules/junit-5-advanced/src/test/java/com/baeldung/displayname/DisplayNameGeneratorUnitTest.java b/testing-modules/junit-5-advanced/src/test/java/com/baeldung/displayname/DisplayNameGeneratorUnitTest.java new file mode 100644 index 0000000000..311539f760 --- /dev/null +++ b/testing-modules/junit-5-advanced/src/test/java/com/baeldung/displayname/DisplayNameGeneratorUnitTest.java @@ -0,0 +1,87 @@ +package com.baeldung.displayname; + +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.lang.reflect.Method; + +@DisplayNameGeneration(DisplayNameGeneratorUnitTest.ReplaceCamelCase.class) +class DisplayNameGeneratorUnitTest { + + @Test + void camelCaseName() { + } + + @Nested + @DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class) + class ANumberIsFizz { + @Test + void ifItIsDivisibleByThree() { + } + + @ParameterizedTest(name = "Number {0} is fizz.") + @ValueSource(ints = { 3, 12, 18 }) + void ifItIsOneOfTheFollowingNumbers(int number) { + } + } + + @Nested + @DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class) + class ANumberIsBuzz { + @Test + void ifItIsDivisibleByFive() { + } + + @ParameterizedTest(name = "Number {0} is buzz.") + @ValueSource(ints = { 5, 10, 20 }) + void ifItIsOneOfTheFollowingNumbers(int number) { + } + } + + static class IndicativeSentences extends ReplaceCamelCase { + @Override + public String generateDisplayNameForNestedClass(Class nestedClass) { + return super.generateDisplayNameForNestedClass(nestedClass) + "..."; + } + + @Override + public String generateDisplayNameForMethod(Class testClass, Method testMethod) { + return replaceCamelCase(testClass.getSimpleName() + " " + testMethod.getName()) + "."; + } + } + + static class ReplaceCamelCase extends DisplayNameGenerator.Standard { + @Override + public String generateDisplayNameForClass(Class testClass) { + return replaceCamelCase(super.generateDisplayNameForClass(testClass)); + } + + @Override + public String generateDisplayNameForNestedClass(Class nestedClass) { + return replaceCamelCase(super.generateDisplayNameForNestedClass(nestedClass)); + } + + @Override + public String generateDisplayNameForMethod(Class testClass, Method testMethod) { + return this.replaceCamelCase(testMethod.getName()) + DisplayNameGenerator.parameterTypesAsString(testMethod); + } + + String replaceCamelCase(String camelCase) { + StringBuilder result = new StringBuilder(); + result.append(camelCase.charAt(0)); + for (int i=1; i + + 4.0.0 + junit-5-basics + 1.0-SNAPSHOT + junit-5-basics + Intro to JUnit 5 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + org.junit.platform + junit-platform-runner + ${junit-platform.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit.vintage.version} + test + + + org.junit.jupiter + junit-jupiter-migrationsupport + ${junit.vintage.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + com.h2database + h2 + ${h2.version} + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-orm + ${spring.version} + + + + + + + src/test/resources + true + + + src/main/resources + true + + + + + + + + filtering + + false + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + **/*IntegrationTest.java + + + + + + + + category + + false + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + com.baeldung.categories.UnitTest + com.baeldung.categories.IntegrationTest + + + + + + + tags + + false + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + UnitTest + IntegrationTest + + + + + + + + + + 5.4.2 + 1.2.0 + 5.4.2 + 1.4.196 + 5.0.6.RELEASE + 2.21.0 + + + diff --git a/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java new file mode 100644 index 0000000000..66f41ee885 --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.junit.tags.example; + +public class Employee { + private int id; + + private String firstName; + + private String lastName; + + private String address; + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getAddress() { + return address; + } + + public void setAddress(final String address) { + this.address = address; + } + +} diff --git a/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java new file mode 100644 index 0000000000..2e9016018e --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java @@ -0,0 +1,58 @@ +package com.baeldung.junit.tags.example; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Repository +public class EmployeeDAO { + + private JdbcTemplate jdbcTemplate; + + private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + private SimpleJdbcInsert simpleJdbcInsert; + + @Autowired + public void setDataSource(final DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + + namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + simpleJdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("EMPLOYEE"); + + } + + public int getCountOfEmployees() { + return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class); + } + + public List getAllEmployees() { + return jdbcTemplate.query("SELECT * FROM EMPLOYEE", new EmployeeRowMapper()); + } + + public int addEmplyee(final int id) { + return jdbcTemplate.update("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)", id, "Bill", "Gates", "USA"); + } + + public int addEmplyeeUsingSimpelJdbcInsert(final Employee emp) { + final Map parameters = new HashMap(); + parameters.put("ID", emp.getId()); + parameters.put("FIRST_NAME", emp.getFirstName()); + parameters.put("LAST_NAME", emp.getLastName()); + parameters.put("ADDRESS", emp.getAddress()); + + return simpleJdbcInsert.execute(parameters); + } + + // for testing + public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } +} diff --git a/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java new file mode 100644 index 0000000000..f480aac9a2 --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java @@ -0,0 +1,21 @@ +package com.baeldung.junit.tags.example; + +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class EmployeeRowMapper implements RowMapper { + + @Override + public Employee mapRow(final ResultSet rs, final int rowNum) throws SQLException { + final Employee employee = new Employee(); + + employee.setId(rs.getInt("ID")); + employee.setFirstName(rs.getString("FIRST_NAME")); + employee.setLastName(rs.getString("LAST_NAME")); + employee.setAddress(rs.getString("ADDRESS")); + + return employee; + } +} diff --git a/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java new file mode 100644 index 0000000000..dc82409df9 --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java @@ -0,0 +1,19 @@ +package com.baeldung.junit.tags.example; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import javax.sql.DataSource; + +@Configuration +@ComponentScan("com.baeldung.junit.tags.example") +public class SpringJdbcConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build(); + } +} \ No newline at end of file diff --git a/testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql new file mode 100644 index 0000000000..c86d35cdae --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE EMPLOYEE +( + ID int NOT NULL PRIMARY KEY, + FIRST_NAME varchar(255), + LAST_NAME varchar(255), + ADDRESS varchar(255), +); \ No newline at end of file diff --git a/testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml b/testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml new file mode 100644 index 0000000000..5fd2699b41 --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql new file mode 100644 index 0000000000..b9ef8fec25 --- /dev/null +++ b/testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql @@ -0,0 +1,7 @@ +INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada'); + +INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA'); + +INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland'); + +INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA'); \ No newline at end of file diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java new file mode 100644 index 0000000000..6aa1652321 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java @@ -0,0 +1,66 @@ +package com.baeldung.categories; + +import com.baeldung.junit.tags.example.Employee; +import com.baeldung.junit.tags.example.EmployeeDAO; +import com.baeldung.junit.tags.example.SpringJdbcConfig; +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +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 = { SpringJdbcConfig.class }, loader = AnnotationConfigContextLoader.class) +public class EmployeeDAOCategoryIntegrationTest { + + @Autowired + private EmployeeDAO employeeDao; + + @Mock + private JdbcTemplate jdbcTemplate; + private EmployeeDAO employeeDAO; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + employeeDAO = new EmployeeDAO(); + employeeDAO.setJdbcTemplate(jdbcTemplate); + } + + @Test + @Category(IntegrationTest.class) + public void testAddEmployeeUsingSimpelJdbcInsert() { + final Employee emp = new Employee(); + emp.setId(12); + emp.setFirstName("testFirstName"); + emp.setLastName("testLastName"); + emp.setAddress("testAddress"); + + Assert.assertEquals(employeeDao.addEmplyeeUsingSimpelJdbcInsert(emp), 1); + } + + @Test + @Category(UnitTest.class) + public void givenNumberOfEmployeeWhenCountEmployeeThenCountMatch() { + + // given + Mockito.when(jdbcTemplate.queryForObject(Mockito.any(String.class), Mockito.eq(Integer.class))) + .thenReturn(1); + + // when + int countOfEmployees = employeeDAO.getCountOfEmployees(); + + // then + Assert.assertThat(countOfEmployees, CoreMatchers.is(1)); + } + +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java new file mode 100644 index 0000000000..252e7ffe64 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java @@ -0,0 +1,12 @@ +package com.baeldung.categories; + +import org.junit.experimental.categories.Categories; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Categories.class) +@IncludeCategory(UnitTest.class) +@SuiteClasses(EmployeeDAOCategoryIntegrationTest.class) +public class EmployeeDAOUnitTestSuite { +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java new file mode 100644 index 0000000000..9ced880ffc --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java @@ -0,0 +1,4 @@ +package com.baeldung.categories; + +public interface IntegrationTest { +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java new file mode 100644 index 0000000000..3790fc1d91 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java @@ -0,0 +1,4 @@ +package com.baeldung.categories; + +public interface UnitTest { +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java new file mode 100644 index 0000000000..d3b6a52726 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.example; + +import com.baeldung.junit.tags.example.Employee; +import com.baeldung.junit.tags.example.EmployeeDAO; +import com.baeldung.junit.tags.example.SpringJdbcConfig; +import org.junit.Assert; +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.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SpringJdbcConfig.class }, loader = AnnotationConfigContextLoader.class) +public class EmployeeDAOIntegrationTest { + + @Autowired + private EmployeeDAO employeeDao; + + @Test + public void testQueryMethod() { + Assert.assertEquals(employeeDao.getAllEmployees().size(), 4); + } + + @Test + public void testUpdateMethod() { + Assert.assertEquals(employeeDao.addEmplyee(5), 1); + } + + @Test + public void testAddEmployeeUsingSimpelJdbcInsert() { + final Employee emp = new Employee(); + emp.setId(11); + emp.setFirstName("testFirstName"); + emp.setLastName("testLastName"); + emp.setAddress("testAddress"); + + Assert.assertEquals(employeeDao.addEmplyeeUsingSimpelJdbcInsert(emp), 1); + } +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java new file mode 100644 index 0000000000..f706af94ad --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.example; + +import com.baeldung.junit.tags.example.EmployeeDAO; +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.jdbc.core.JdbcTemplate; + +public class EmployeeUnitTest { + + @Mock + private JdbcTemplate jdbcTemplate; + + private EmployeeDAO employeeDAO; + + @BeforeEach + public void setup() { + MockitoAnnotations.initMocks(this); + employeeDAO = new EmployeeDAO(); + employeeDAO.setJdbcTemplate(jdbcTemplate); + } + + @Test + public void givenNumberOfEmployeeWhenCountEmployeeThenCountMatch() { + + // given + Mockito.when(jdbcTemplate.queryForObject(Mockito.any(String.class), Mockito.eq(Integer.class))) + .thenReturn(1); + + // when + int countOfEmployees = employeeDAO.getCountOfEmployees(); + + // then + Assert.assertThat(countOfEmployees, CoreMatchers.is(1)); + } +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/SharedTemporaryDirectoryUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/SharedTemporaryDirectoryUnitTest.java new file mode 100644 index 0000000000..9483a33143 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/SharedTemporaryDirectoryUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.extensions.tempdir; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertLinesMatch; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.io.TempDir; + +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; + +@TestMethodOrder(OrderAnnotation.class) +class SharedTemporaryDirectoryUnitTest { + + @TempDir + static Path sharedTempDir; + + @Test + @Order(1) + void givenFieldWithSharedTempDirectoryPath_whenWriteToFile_thenContentIsCorrect() throws IOException { + Path numbers = sharedTempDir.resolve("numbers.txt"); + + List lines = Arrays.asList("1", "2", "3"); + Files.write(numbers, lines); + + assertAll( + () -> assertTrue("File should exist", Files.exists(numbers)), + () -> assertLinesMatch(lines, Files.readAllLines(numbers))); + + Files.createTempDirectory("bpb"); + } + + @Test + @Order(2) + void givenAlreadyWrittenToSharedFile_whenCheckContents_thenContentIsCorrect() throws IOException { + Path numbers = sharedTempDir.resolve("numbers.txt"); + + assertLinesMatch(Arrays.asList("1", "2", "3"), Files.readAllLines(numbers)); + } + +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/TemporaryDirectoryUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/TemporaryDirectoryUnitTest.java new file mode 100644 index 0000000000..c6f1a7cd77 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/extensions/tempdir/TemporaryDirectoryUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.extensions.tempdir; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertLinesMatch; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +class TemporaryDirectoryUnitTest { + + @Test + void givenTestMethodWithTempDirectoryPath_whenWriteToFile_thenContentIsCorrect(@TempDir Path tempDir) throws IOException { + Path numbers = tempDir.resolve("numbers.txt"); + + List lines = Arrays.asList("1", "2", "3"); + Files.write(numbers, lines); + + assertAll( + () -> assertTrue("File should exist", Files.exists(numbers)), + () -> assertLinesMatch(lines, Files.readAllLines(numbers))); + } + + @TempDir + File anotherTempDir; + + @Test + void givenFieldWithTempDirectoryFile_whenWriteToFile_thenContentIsCorrect() throws IOException { + assertTrue("Should be a directory ", this.anotherTempDir.isDirectory()); + + File letters = new File(anotherTempDir, "letters.txt"); + List lines = Arrays.asList("x", "y", "z"); + + Files.write(letters.toPath(), lines); + + assertAll( + () -> assertTrue("File should exist", Files.exists(letters.toPath())), + () -> assertLinesMatch(lines, Files.readAllLines(letters.toPath()))); + } + +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java new file mode 100644 index 0000000000..20fa372abd --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.resourcedirectory; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ReadResourceDirectoryUnitTest { + + @Test + public void givenResourcePath_whenReadAbsolutePathWithFile_thenAbsolutePathEndsWithDirectory() { + String path = "src/test/resources"; + + File file = new File(path); + String absolutePath = file.getAbsolutePath(); + + System.out.println(absolutePath); + Assert.assertTrue(absolutePath.endsWith("src/test/resources")); + } + + @Test + public void givenResourcePath_whenReadAbsolutePathWithPaths_thenAbsolutePathEndsWithDirectory() { + Path resourceDirectory = Paths.get("src", "test", "resources"); + + String absolutePath = resourceDirectory.toFile().getAbsolutePath(); + + System.out.println(absolutePath); + Assert.assertTrue(absolutePath.endsWith("src/test/resources")); + } + + @Test + public void givenResourceFile_whenReadResourceWithClassLoader_thenPathEndWithFilename() { + String resourceName = "example_resource.txt"; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource(resourceName).getFile()); + String absolutePath = file.getAbsolutePath(); + + System.out.println(absolutePath); + Assert.assertTrue(absolutePath.endsWith("/example_resource.txt")); + } + +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java new file mode 100644 index 0000000000..bcd76cb4c2 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.tags; + +import com.baeldung.junit.tags.example.Employee; +import com.baeldung.junit.tags.example.EmployeeDAO; +import com.baeldung.junit.tags.example.SpringJdbcConfig; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { SpringJdbcConfig.class }, loader = AnnotationConfigContextLoader.class) +public class EmployeeDAOIntegrationTest { + + @Autowired + private EmployeeDAO employeeDao; + + @Mock + private JdbcTemplate jdbcTemplate; + private EmployeeDAO employeeDAO; + + @BeforeEach + public void setup() { + MockitoAnnotations.initMocks(this); + employeeDAO = new EmployeeDAO(); + employeeDAO.setJdbcTemplate(jdbcTemplate); + } + + @Test + @Tag("IntegrationTest") + public void testAddEmployeeUsingSimpelJdbcInsert() { + final Employee emp = new Employee(); + emp.setId(12); + emp.setFirstName("testFirstName"); + emp.setLastName("testLastName"); + emp.setAddress("testAddress"); + + Assertions.assertEquals(employeeDao.addEmplyeeUsingSimpelJdbcInsert(emp), 1); + } + + @Test + @Tag("UnitTest") + public void givenNumberOfEmployeeWhenCountEmployeeThenCountMatch() { + + // given + Mockito.when(jdbcTemplate.queryForObject(Mockito.any(String.class), Mockito.eq(Integer.class))) + .thenReturn(1); + + // when + int countOfEmployees = employeeDAO.getCountOfEmployees(); + + // then + Assertions.assertEquals(1, countOfEmployees); + } + +} diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java new file mode 100644 index 0000000000..783e5a81a2 --- /dev/null +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java @@ -0,0 +1,12 @@ +package com.baeldung.tags; + +import org.junit.platform.runner.JUnitPlatform; +import org.junit.platform.suite.api.IncludeTags; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.runner.RunWith; + +@RunWith(JUnitPlatform.class) +@SelectPackages("com.baeldung.tags") +@IncludeTags("UnitTest") +public class EmployeeDAOTestSuite { +} diff --git a/testing-modules/junit-5-basics/src/test/resources/example_resource.txt b/testing-modules/junit-5-basics/src/test/resources/example_resource.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index 1fbd7a4a5e..47db6587b4 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -3,12 +3,12 @@ - [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) +- [JUnit5 @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) @@ -16,3 +16,5 @@ - [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java) - [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/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index b7600267d9..b3074635a7 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -21,19 +21,34 @@ junit-platform-engine ${junit.platform.version} + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + org.junit.platform junit-platform-runner ${junit.platform.version} test - + org.junit.vintage junit-vintage-engine ${junit.vintage.version} test - + org.junit.jupiter junit-jupiter-migrationsupport ${junit.vintage.version} @@ -98,13 +113,6 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - - org.codehaus.mojo @@ -125,14 +133,13 @@ - 5.3.1 + 5.4.2 2.23.0 - 1.2.0 - 5.2.0 + 1.4.2 + 5.4.2 2.8.2 - 1.4.196 2.0.0-RC.1 - 2.21.0 + 2.22.0 1.6.0 5.0.1.RELEASE diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java index 31b6e14d6c..f1f7c531f2 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java @@ -2,7 +2,21 @@ package com.baeldung; import static java.time.Duration.ofSeconds; import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.junit.jupiter.api.Assertions.assertLinesMatch; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTimeout; +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; import java.util.LinkedList; @@ -91,11 +105,12 @@ public class AssertionUnitTest { @Test public void givenMultipleAssertion_whenAssertingAll_thenOK() { + Object obj = null; assertAll( "heading", () -> assertEquals(4, 2 * 2, "4 is 2 times 2"), () -> assertEquals("java", "JAVA".toLowerCase()), - () -> assertEquals(null, null, "null is equal to null") + () -> assertEquals(obj, null, "null is equal to null") ); } diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java new file mode 100644 index 0000000000..db37e9a6d2 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/MultipleExtensionsUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.extension.RegisterExtension; +import com.baeldung.extensions.EmployeeDatabaseSetupExtension; + +public class MultipleExtensionsUnitTest { + + @Order(1) + @RegisterExtension + static EmployeeDatabaseSetupExtension SECOND_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbTwo;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @Order(0) + @RegisterExtension + static EmployeeDatabaseSetupExtension FIRST_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbOne;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @RegisterExtension + static EmployeeDatabaseSetupExtension LAST_DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:DbLast;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + @Test + public void justDemonstratingTheIdea() { + // empty test + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java new file mode 100644 index 0000000000..a29fafd193 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/ProgrammaticEmployeesUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung; + +import java.sql.SQLException; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; + +import com.baeldung.helpers.Employee; +import com.baeldung.extensions.EmployeeDaoParameterResolver; +import com.baeldung.extensions.EmployeeDatabaseSetupExtension; +import com.baeldung.extensions.EnvironmentExtension; +import com.baeldung.helpers.EmployeeJdbcDao; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith({ EnvironmentExtension.class, EmployeeDaoParameterResolver.class }) +public class ProgrammaticEmployeesUnitTest { + + private EmployeeJdbcDao employeeDao; + + @RegisterExtension static EmployeeDatabaseSetupExtension DB = + new EmployeeDatabaseSetupExtension("jdbc:h2:mem:AnotherDb;DB_CLOSE_DELAY=-1", "org.h2.Driver", "sa", ""); + + public ProgrammaticEmployeesUnitTest(EmployeeJdbcDao employeeDao) { + this.employeeDao = employeeDao; + } + + @Test + public void whenAddEmployee_thenGetEmployee() throws SQLException { + Employee emp = new Employee(1, "john"); + employeeDao.add(emp); + assertEquals(1, employeeDao.findAll().size()); + } + + @Test + public void whenGetEmployees_thenEmptyList() throws SQLException { + assertEquals(0, employeeDao.findAll().size()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java b/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java index f9766d2bd9..2e477084aa 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java @@ -18,9 +18,9 @@ public class TestLauncher { //@formatter:off LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() - .selectors(selectClass("com.baeldung.EmployeesTest")) + .selectors(selectClass("com.baeldung.EmployeesUnitTest")) .configurationParameter("junit.conditions.deactivate", "com.baeldung.extensions.*") - .configurationParameter("junit.extensions.autodetection.enabled", "true") + .configurationParameter("junit.jupiter.extensions.autodetection.enabled", "true") .build(); //@formatter:on 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"); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java b/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java index 69e420b28a..f124703690 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/extensions/EmployeeDatabaseSetupExtension.java @@ -15,10 +15,20 @@ import com.baeldung.helpers.JdbcConnectionUtil; public class EmployeeDatabaseSetupExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { - private Connection con = JdbcConnectionUtil.getConnection(); - private EmployeeJdbcDao employeeDao = new EmployeeJdbcDao(con); + private Connection con; + private EmployeeJdbcDao employeeDao; private Savepoint savepoint; + public EmployeeDatabaseSetupExtension() { + con = JdbcConnectionUtil.getConnection(); + employeeDao = new EmployeeJdbcDao(con); + } + + public EmployeeDatabaseSetupExtension(String jdbcUrl, String driver, String username, String password) { + con = JdbcConnectionUtil.getConnection(jdbcUrl, driver, username, password); + employeeDao = new EmployeeJdbcDao(con); + } + @Override public void afterAll(ExtensionContext context) throws SQLException { if (con != null) { diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java index 7600f763cd..4b274cff39 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/EmployeeJdbcDao.java @@ -19,7 +19,7 @@ public class EmployeeJdbcDao { } public void createTable() throws SQLException { - String createQuery = "CREATE TABLE employees(id long primary key, firstName varchar(50))"; + String createQuery = "CREATE TABLE IF NOT EXISTS employees(id long primary key, firstName varchar(50))"; PreparedStatement pstmt = con.prepareStatement(createQuery); pstmt.execute(); diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java index f380f9674c..ccba627234 100644 --- a/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java +++ b/testing-modules/junit-5/src/test/java/com/baeldung/helpers/JdbcConnectionUtil.java @@ -11,22 +11,49 @@ public class JdbcConnectionUtil { private static Connection con; public static Connection getConnection() { - if (con == null) { + if (con == null || isClosed(con)) { try { Properties props = new Properties(); props.load(JdbcConnectionUtil.class.getResourceAsStream("jdbc.properties")); - Class.forName(props.getProperty("jdbc.driver")); - con = DriverManager.getConnection(props.getProperty("jdbc.url"), props.getProperty("jdbc.user"), props.getProperty("jdbc.password")); + + String jdbcUrl = props.getProperty("jdbc.url"); + String driver = props.getProperty("jdbc.driver"); + String username = props.getProperty("jdbc.user"); + String password = props.getProperty("jdbc.password"); + con = getConnection(jdbcUrl, driver, username, password); return con; } catch (IOException exc) { exc.printStackTrace(); + } + + return null; + } + return con; + } + + public static Connection getConnection(String jdbcUrl, String driver, String username, String password) { + if (con == null || isClosed(con)) { + try { + Class.forName(driver); + con = DriverManager.getConnection(jdbcUrl, username, password); + return con; } catch (ClassNotFoundException exc) { exc.printStackTrace(); } catch (SQLException exc) { exc.printStackTrace(); } + return null; } + return con; } + + private static boolean isClosed(Connection con) { + try { + return con.isClosed(); + } catch (SQLException e) { + return true; + } + } } diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java new file mode 100644 index 0000000000..d62ca0c666 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.junit5.order; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.MethodOrderer.Alphanumeric; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +@TestMethodOrder(Alphanumeric.class) +public class AlphanumericOrderUnitTest { + private static StringBuilder output = new StringBuilder(""); + + @Test + public void myATest() { + output.append("A"); + } + + @Test + public void myBTest() { + output.append("B"); + } + + @Test + public void myaTest() { + output.append("a"); + } + + @AfterAll + public static void assertOutput() { + assertEquals(output.toString(), "ABa"); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java new file mode 100644 index 0000000000..e76230de63 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java @@ -0,0 +1,12 @@ +package com.baeldung.junit5.order; + +import org.junit.jupiter.api.MethodDescriptor; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.MethodOrdererContext; + +public class CustomOrder implements MethodOrderer{ + @Override + public void orderMethods(MethodOrdererContext context) { + context.getMethodDescriptors().sort((MethodDescriptor m1, MethodDescriptor m2)->m1.getMethod().getName().compareToIgnoreCase(m2.getMethod().getName())); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java new file mode 100644 index 0000000000..fa45921879 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.junit5.order; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +@TestMethodOrder(CustomOrder.class) +public class CustomOrderUnitTest { + private static StringBuilder output = new StringBuilder(""); + + @Test + public void myATest() { + output.append("A"); + } + + @Test + public void myBTest() { + output.append("B"); + } + + @Test + public void myaTest() { + output.append("a"); + } + + + @AfterAll + public static void assertOutput() { + assertEquals(output.toString(), "AaB"); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java new file mode 100644 index 0000000000..3d931a4158 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.junit5.order; + +import static org.junit.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +@TestMethodOrder(OrderAnnotation.class) +public class OrderAnnotationUnitTest { + private static StringBuilder output = new StringBuilder(""); + + @Test + @Order(1) + public void firstTest() { + output.append("a"); + } + + @Test + @Order(2) + public void secondTest() { + output.append("b"); + } + + @Test + @Order(3) + public void thirdTest() { + output.append("c"); + } + + @AfterAll + public static void assertOutput() { + assertEquals(output.toString(), "abc"); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java new file mode 100644 index 0000000000..1d2c76d37b --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java @@ -0,0 +1,19 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; + +import java.util.stream.Stream; + +class BlankStringsArgumentsProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of((String) null), + Arguments.of(""), + Arguments.of(" ") + ); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java new file mode 100644 index 0000000000..0b2068dbf1 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.EnumSource; + +import java.time.Month; +import java.util.EnumSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EnumsUnitTest { + + @ParameterizedTest + @EnumSource(Month.class) + void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) { + int monthNumber = month.getValue(); + assertTrue(monthNumber >= 1 && monthNumber <= 12); + } + + @ParameterizedTest(name = "{index} {0} is 30 days long") + @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"}) + void someMonths_Are30DaysLong(Month month) { + final boolean isALeapYear = false; + assertEquals(30, month.length(isALeapYear)); + } + + @ParameterizedTest + @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE) + void exceptFourMonths_OthersAre31DaysLong(Month month) { + final boolean isALeapYear = false; + assertEquals(31, month.length(isALeapYear)); + } + + @ParameterizedTest + @EnumSource(value = Month.class, names = ".+BER", mode = EnumSource.Mode.MATCH_ANY) + void fourMonths_AreEndingWithBer(Month month) { + EnumSet months = EnumSet.of(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER); + assertTrue(months.contains(month)); + } + + @ParameterizedTest + @CsvSource({"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"}) + void someMonths_Are30DaysLongCsv(Month month) { + final boolean isALeapYear = false; + assertEquals(30, month.length(isALeapYear)); + } + +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java new file mode 100644 index 0000000000..95487705f5 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LocalDateUnitTest { + + @ParameterizedTest + @CsvSource({"2018/12/25,2018", "2019/02/11,2019"}) + void getYear_ShouldWorkAsExpected(@ConvertWith(SlashyDateConverter.class) LocalDate date, int expected) { + assertEquals(expected, date.getYear()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java new file mode 100644 index 0000000000..8a9b229aac --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java @@ -0,0 +1,8 @@ +package com.baeldung.parameterized; + +public class Numbers { + + public static boolean isOdd(int number) { + return number % 2 != 0; + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java new file mode 100644 index 0000000000..b3a3371bb2 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java @@ -0,0 +1,15 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NumbersUnitTest { + + @ParameterizedTest + @ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE}) + void isOdd_ShouldReturnTrueForOddNumbers(int number) { + assertTrue(Numbers.isOdd(number)); + } +} \ No newline at end of file diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java new file mode 100644 index 0000000000..225f11ba29 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java @@ -0,0 +1,20 @@ +package com.baeldung.parameterized; + +class Person { + + private final String firstName; + private final String middleName; + private final String lastName; + + public Person(String firstName, String middleName, String lastName) { + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + } + + public String fullName() { + if (middleName == null || middleName.trim().isEmpty()) return String.format("%s %s", firstName, lastName); + + return String.format("%s %s %s", firstName, middleName, lastName); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java new file mode 100644 index 0000000000..df2ddc9e66 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java @@ -0,0 +1,15 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.aggregator.ArgumentsAggregationException; +import org.junit.jupiter.params.aggregator.ArgumentsAggregator; + +class PersonAggregator implements ArgumentsAggregator { + + @Override + public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) + throws ArgumentsAggregationException { + return new Person(accessor.getString(1), accessor.getString(2), accessor.getString(3)); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java new file mode 100644 index 0000000000..b30ecc748e --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.aggregator.AggregateWith; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PersonUnitTest { + + @ParameterizedTest + @CsvSource({"Isaac,,Newton, Isaac Newton", "Charles,Robert,Darwin,Charles Robert Darwin"}) + void fullName_ShouldGenerateTheExpectedFullName(ArgumentsAccessor argumentsAccessor) { + String firstName = argumentsAccessor.getString(0); + String middleName = (String) argumentsAccessor.get(1); + String lastName = argumentsAccessor.get(2, String.class); + String expectedFullName = argumentsAccessor.getString(3); + + Person person = new Person(firstName, middleName, lastName); + assertEquals(expectedFullName, person.fullName()); + } + + @ParameterizedTest + @CsvSource({"Isaac Newton,Isaac,,Newton", "Charles Robert Darwin,Charles,Robert,Darwin"}) + void fullName_ShouldGenerateTheExpectedFullName(String expectedFullName, + @AggregateWith(PersonAggregator.class) Person person) { + + assertEquals(expectedFullName, person.fullName()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java new file mode 100644 index 0000000000..40773d29a9 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java @@ -0,0 +1,27 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; + +import java.time.LocalDate; + +class SlashyDateConverter implements ArgumentConverter { + + @Override + public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + if (!(source instanceof String)) + throw new IllegalArgumentException("The argument should be a string: " + source); + + try { + String[] parts = ((String) source).split("/"); + int year = Integer.parseInt(parts[0]); + int month = Integer.parseInt(parts[1]); + int day = Integer.parseInt(parts[2]); + + return LocalDate.of(year, month, day); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to convert", e); + } + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java new file mode 100644 index 0000000000..bc9f881bd4 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java @@ -0,0 +1,10 @@ +package com.baeldung.parameterized; + +import java.util.stream.Stream; + +public class StringParams { + + static Stream blankStrings() { + return Stream.of(null, "", " "); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java new file mode 100644 index 0000000000..f8e29f6b7f --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java @@ -0,0 +1,8 @@ +package com.baeldung.parameterized; + +class Strings { + + static boolean isBlank(String input) { + return input == null || input.trim().isEmpty(); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java new file mode 100644 index 0000000000..6aea7668f1 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java @@ -0,0 +1,131 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.*; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class StringsUnitTest { + + static Stream arguments = Stream.of( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + + @ParameterizedTest + @VariableSource("arguments") + void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @ValueSource(strings = {"", " "}) + void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource("provideStringsForIsBlank") + void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource // Please note method name is not provided + void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource("com.baeldung.parameterized.StringParams#blankStrings") + void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @ArgumentsSource(BlankStringsArgumentsProvider.class) + void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider(String input) { + assertTrue(Strings.isBlank(input)); + } + + private static Stream isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument() { + return Stream.of(null, "", " "); + } + + @ParameterizedTest + @MethodSource("provideStringsForIsBlankList") + void isBlank_ShouldReturnTrueForNullOrBlankStringsList(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"}) // Passing a CSV pair per test execution + void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) { + String actualValue = input.toUpperCase(); + assertEquals(expected, actualValue); + } + + @ParameterizedTest + @CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter =':') // Using : as the column separator. + void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) { + String actualValue = input.toLowerCase(); + assertEquals(expected, actualValue); + } + + @ParameterizedTest + @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1) + void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) { + String actualValue = input.toUpperCase(); + assertEquals(expected, actualValue); + } + + @ParameterizedTest + @NullSource + void isBlank_ShouldReturnTrueForNullInputs(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @EmptySource + void isBlank_ShouldReturnTrueForEmptyStrings(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @NullAndEmptySource + void isBlank_ShouldReturnTrueForNullAndEmptyStrings(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\t", "\n"}) + void isBlank_ShouldReturnTrueForAllTypesOfBlankStrings(String input) { + assertTrue(Strings.isBlank(input)); + } + + private static Stream provideStringsForIsBlank() { + return Stream.of( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } + + private static List provideStringsForIsBlankList() { + return Arrays.asList( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } +} \ No newline at end of file diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java new file mode 100644 index 0000000000..a96d01e854 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java @@ -0,0 +1,45 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.support.AnnotationConsumer; + +import java.lang.reflect.Field; +import java.util.stream.Stream; + +class VariableArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { + + private String variableName; + + @Override + public Stream provideArguments(ExtensionContext context) { + return context.getTestClass() + .map(this::getField) + .map(this::getValue) + .orElseThrow(() -> new IllegalArgumentException("Failed to load test arguments")); + } + + @Override + public void accept(VariableSource variableSource) { + variableName = variableSource.value(); + } + + private Field getField(Class clazz) { + try { + return clazz.getDeclaredField(variableName); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + private Stream getValue(Field field) { + Object value = null; + try { + value = field.get(null); + } catch (Exception ignored) {} + + return value == null ? null : (Stream) value; + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java new file mode 100644 index 0000000000..9c1d07c1be --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java @@ -0,0 +1,19 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@ArgumentsSource(VariableArgumentsProvider.class) +public @interface VariableSource { + + /** + * Represents the name of the static variable to load the test arguments from. + * + * @return Static variable name. + */ + String value(); +} diff --git a/testing-modules/junit-5/src/test/resources/data.csv b/testing-modules/junit-5/src/test/resources/data.csv new file mode 100644 index 0000000000..321554cc23 --- /dev/null +++ b/testing-modules/junit-5/src/test/resources/data.csv @@ -0,0 +1,4 @@ +input,expected +test,TEST +tEst,TEST +Java,JAVA \ No newline at end of file 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) - diff --git a/testing-modules/junit5-migration/pom.xml b/testing-modules/junit5-migration/pom.xml index 9d9d418774..536953afc8 100644 --- a/testing-modules/junit5-migration/pom.xml +++ b/testing-modules/junit5-migration/pom.xml @@ -1,9 +1,7 @@ - 4.0.0 - junit5-migration 1.0-SNAPSHOT junit5-migration diff --git a/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java b/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java index d1d08c6e62..d225e4547e 100644 --- a/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java +++ b/testing-modules/junit5-migration/src/test/java/com/baeldung/junit5/AssertionUnitTest.java @@ -34,7 +34,7 @@ public class AssertionUnitTest { "heading", () -> assertEquals(4, 2 * 2, "4 is 2 times 2"), () -> assertEquals("java", "JAVA".toLowerCase()), - () -> assertEquals(null, null, "null is equal to null") + () -> assertEquals((String) null, (String) null, "null is equal to null") ); } } diff --git a/testing-modules/load-testing-comparison/pom.xml b/testing-modules/load-testing-comparison/pom.xml index 42614d310b..44014e96ab 100644 --- a/testing-modules/load-testing-comparison/pom.xml +++ b/testing-modules/load-testing-comparison/pom.xml @@ -13,19 +13,6 @@ ../../pom.xml - - 1.8 - 1.8 - UTF-8 - 2.11.12 - 2.2.5 - 3.2.2 - 2.2.1 - 5.0 - 3.11 - 2.0.5.RELEASE - - io.gatling @@ -55,7 +42,7 @@ com.fasterxml.jackson.core jackson-databind - 2.9.4 + ${jackson.version} org.springframework.boot @@ -81,12 +68,12 @@ com.h2database h2 - 1.4.197 + ${h2.version} org.projectlombok lombok - 1.18.2 + ${lombok.version} compile @@ -146,4 +133,19 @@ + + + 1.8 + 1.8 + UTF-8 + 2.11.12 + 2.2.5 + 3.2.2 + 2.2.1 + 5.0 + 3.11 + 2.0.5.RELEASE + 1.4.197 + +
\ No newline at end of file diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx index da32a13a22..97640dfac7 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx @@ -1,5 +1,5 @@ - + @@ -25,80 +25,116 @@ - - true - 1 - - - - - - Content-Type - application/json + + + + Content-Type + application/json + + + + + + true + + + + false + {"customerRewardsId":null,"customerId":${random},"transactionDate":null} + = - + + localhost + 8080 + http + + /transactions/add + POST + true + false + true + false + + + + + + + txnId + $.id + 1 + all + foo + - + + txnDate + $.transactionDate + 1 + Never + + + + custId + $.customerId + 1 + all + bob + + + + + + + + localhost + 8080 + + + /rewards/find/${custId} + GET + true + false + true + false + + + + + + + rwdId + $.id + 1 + 0 + all + + + + + ${__jexl3(${rwdId} == 0,)} + true + true + + + true false - {"customerRewardsId":null,"customerId":${random},"transactionDate":null} + {"customerId":${custId}} = localhost 8080 - http - - /transactions/add - POST - true - false - true - false - - - - - - - txnId - $.id - 1 - all - foo - - - - txnDate - $.transactionDate - 1 - Never - - - - custId - $.customerId - 1 - all - bob - - - - - - - - localhost - 8080 - /rewards/find/${custId} - GET + /rewards/add + POST true false true @@ -112,98 +148,57 @@ rwdId $.id 1 - 0 + bar all - - ${rwdId} == 0 - true - - - - true - - - - false - {"customerId":${custId}} - = - - - - localhost - 8080 - - - /rewards/add - POST - true - false - true - false - - - - - - - rwdId - $.id - 1 - bar - all - - - - - - true - - - - false - {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"} - = - - - - localhost - 8080 - - - /transactions/add - POST - true - false - true - false - - - - - - - - - - localhost - 8080 - - - /transactions/findAll/${rwdId} - GET - true - false - true - false - - - - - + + true + + + + false + {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"} + = + + + + localhost + 8080 + + + /transactions/add + POST + true + false + true + false + + + + + + + + + + localhost + 8080 + + + /transactions/findAll/${rwdId} + GET + true + false + true + false + + + + + 10000 1 @@ -213,7 +208,7 @@ random - + false saveConfig diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md index ee443df81a..5c9e8fc81a 100644 --- a/testing-modules/mockito-2/README.md +++ b/testing-modules/mockito-2/README.md @@ -2,7 +2,4 @@ - [Mockito’s Java 8 Features](http://www.baeldung.com/mockito-2-java-8) - [Lazy Verification with Mockito 2](http://www.baeldung.com/mockito-2-lazy-verification) - -## Mockito 2 and Java 8 Tips - -Examples on how to leverage Java 8 new features with Mockito version 2 +- [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception) diff --git a/testing-modules/mockito-2/pom.xml b/testing-modules/mockito-2/pom.xml index 5f60566566..e319dd9edd 100644 --- a/testing-modules/mockito-2/pom.xml +++ b/testing-modules/mockito-2/pom.xml @@ -4,8 +4,8 @@ com.baeldung mockito-2 0.0.1-SNAPSHOT - jar mockito-2 + jar com.baeldung diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/ExpectedTestFailureRule.java b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/ExpectedTestFailureRule.java new file mode 100644 index 0000000000..53ad60a2fa --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/ExpectedTestFailureRule.java @@ -0,0 +1,51 @@ +package com.baeldung.mockito.misusing; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.rules.MethodRule; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +public class ExpectedTestFailureRule implements MethodRule { + + private final MethodRule testedRule; + private FailureAssert failureAssert = null; + + public ExpectedTestFailureRule(MethodRule testedRule) { + this.testedRule = testedRule; + } + + @Override + public Statement apply(final Statement base, final FrameworkMethod method, final Object target) { + return new Statement() { + public void evaluate() throws Throwable { + try { + testedRule.apply(base, method, target) + .evaluate(); + } catch (Throwable t) { + if (failureAssert == null) { + throw t; + } + failureAssert.doAssert(t); + return; + } + } + }; + } + + @SuppressWarnings("unchecked") + public void expectedFailure(final Class expected) { + FailureAssert assertion = t -> Assert.assertThat(t, Matchers.isA((Class) expected)); + this.expectedFailure(assertion); + } + + private void expectedFailure(FailureAssert failureAssert) { + this.failureAssert = failureAssert; + } + + @FunctionalInterface + private interface FailureAssert { + abstract void doAssert(Throwable t); + } + +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/MockitoUnecessaryStubUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/MockitoUnecessaryStubUnitTest.java new file mode 100644 index 0000000000..00edb699de --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/misusing/MockitoUnecessaryStubUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.mockito.misusing; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.exceptions.misusing.UnnecessaryStubbingException; +import org.mockito.junit.MockitoJUnit; +import org.mockito.quality.Strictness; + +public class MockitoUnecessaryStubUnitTest { + + @Rule + public ExpectedTestFailureRule rule = new ExpectedTestFailureRule(MockitoJUnit.rule() + .strictness(Strictness.STRICT_STUBS)); + + @Mock + private ArrayList mockList; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException() { + rule.expectedFailure(UnnecessaryStubbingException.class); + + when(mockList.add("one")).thenReturn(true); + when(mockList.get(anyInt())).thenReturn("hello"); + + assertEquals("List should contain hello", "hello", mockList.get(1)); + } + + @Test + public void givenLenientdStub_whenInvokingGetThenDontThrowUnnecessaryStubbingException() { + lenient().when(mockList.add("one")) + .thenReturn(true); + when(mockList.get(anyInt())).thenReturn("hello"); + + assertEquals("List should contain hello", "hello", mockList.get(1)); + } + +} diff --git a/testing-modules/mockito/README.md b/testing-modules/mockito/README.md index e1b9c27523..59954784f9 100644 --- a/testing-modules/mockito/README.md +++ b/testing-modules/mockito/README.md @@ -7,15 +7,14 @@ - [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) - [Mocking Void Methods with Mockito](http://www.baeldung.com/mockito-void-methods) - [Mocking of Private Methods Using PowerMock](http://www.baeldung.com/powermock-private-method) - [Mock Final Classes and Methods with Mockito](http://www.baeldung.com/mockito-final) -- [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers) -- [Hamcrest File Matchers](http://www.baeldung.com/hamcrest-file-matchers) - [Hamcrest Custom Matchers](http://www.baeldung.com/hamcrest-custom-matchers) - [Hamcrest Common Core Matchers](http://www.baeldung.com/hamcrest-core-matchers) - [Testing Callbacks with Mockito](http://www.baeldung.com/mockito-callbacks) +- [Using Hamcrest Number Matchers](https://www.baeldung.com/hamcrest-number-matchers) diff --git a/testing-modules/mockito/pom.xml b/testing-modules/mockito/pom.xml index acdd7eb2ac..19dbaa0dc1 100644 --- a/testing-modules/mockito/pom.xml +++ b/testing-modules/mockito/pom.xml @@ -33,7 +33,7 @@ org.eclipse.persistence javax.persistence - 2.1.1 + ${javax.persistence.version} @@ -99,6 +99,7 @@ 1.7.0 2.0.0.0 + 2.1.1 \ No newline at end of file diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/MockitoInjectIntoSpyUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/MockitoInjectIntoSpyUnitTest.java new file mode 100644 index 0000000000..4f5ceb04e7 --- /dev/null +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/MockitoInjectIntoSpyUnitTest.java @@ -0,0 +1,38 @@ +package org.baeldung.mockito; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.*; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +@RunWith(MockitoJUnitRunner.class) +public class MockitoInjectIntoSpyUnitTest { + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + spyDic = Mockito.spy(new MyDictionary(wordMap)); + } + + @Mock + private Map wordMap; + + @InjectMocks + private MyDictionary dic = new MyDictionary(); + + private MyDictionary spyDic; + + @Test + public void whenUseInjectMocksAnnotation_thenCorrect2() { + Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning"); + + assertEquals("aMeaning", spyDic.getMeaning("aWord")); + } +} diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java index 8a0ea92502..9492c90d11 100644 --- a/testing-modules/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java @@ -11,6 +11,10 @@ class MyDictionary { wordMap = new HashMap<>(); } + MyDictionary(Map wordMap) { + this.wordMap = wordMap; + } + public void add(final String word, final String meaning) { wordMap.put(word, meaning); } 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!")); + } + } + +} 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) 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) diff --git a/testing-modules/mocks/mock-comparisons/pom.xml b/testing-modules/mocks/mock-comparisons/pom.xml index ae36280300..e454f124ce 100644 --- a/testing-modules/mocks/mock-comparisons/pom.xml +++ b/testing-modules/mocks/mock-comparisons/pom.xml @@ -49,7 +49,6 @@ 2.21.0 3.5.1 1.41 - diff --git a/testing-modules/mocks/pom.xml b/testing-modules/mocks/pom.xml index 6473f07c13..ecc8b61a6d 100644 --- a/testing-modules/mocks/pom.xml +++ b/testing-modules/mocks/pom.xml @@ -1,6 +1,9 @@ 4.0.0 + mocks + mocks + pom com.baeldung @@ -9,10 +12,6 @@ ../../ - mocks - mocks - pom - mock-comparisons jmockit diff --git a/testing-modules/parallel-tests-junit/math-test-functions/pom.xml b/testing-modules/parallel-tests-junit/math-test-functions/pom.xml index 18d2b562f3..cc9f27de05 100644 --- a/testing-modules/parallel-tests-junit/math-test-functions/pom.xml +++ b/testing-modules/parallel-tests-junit/math-test-functions/pom.xml @@ -4,25 +4,25 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 + math-test-functions + math-test-functions + http://maven.apache.org + com.baeldung parallel-tests-junit 0.0.1-SNAPSHOT - math-test-functions - math-test-functions - http://maven.apache.org - - UTF-8 - + junit junit - 4.12 + ${junit.version} test + @@ -45,4 +45,8 @@ + + + UTF-8 + diff --git a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionTest.java b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionUnitTest.java similarity index 93% rename from testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionTest.java rename to testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionUnitTest.java index df0aa695fc..1f048b305f 100644 --- a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionTest.java +++ b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ArithmeticFunctionUnitTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; -public class ArithmeticFunctionTest { +public class ArithmeticFunctionUnitTest { @Test public void test_addingIntegers_returnsSum() { diff --git a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionTest.java b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionUnitTest.java similarity index 87% rename from testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionTest.java rename to testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionUnitTest.java index 4f72c87279..839b6c2cf3 100644 --- a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionTest.java +++ b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/ComparisonFunctionUnitTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; -public class ComparisonFunctionTest { +public class ComparisonFunctionUnitTest { @Test public void test_findMax() { diff --git a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/FunctionTestSuite.java b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/FunctionTestSuite.java index 4fe551b365..d12eab5c51 100644 --- a/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/FunctionTestSuite.java +++ b/testing-modules/parallel-tests-junit/math-test-functions/src/test/java/com/baeldung/FunctionTestSuite.java @@ -5,7 +5,7 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({ ComparisonFunctionTest.class, ArithmeticFunctionTest.class }) +@SuiteClasses({ ComparisonFunctionUnitTest.class, ArithmeticFunctionUnitTest.class }) public class FunctionTestSuite { } diff --git a/testing-modules/parallel-tests-junit/pom.xml b/testing-modules/parallel-tests-junit/pom.xml index ecca8b3930..993974046c 100644 --- a/testing-modules/parallel-tests-junit/pom.xml +++ b/testing-modules/parallel-tests-junit/pom.xml @@ -1,14 +1,22 @@ - 4.0.0 - com.baeldung - parallel-tests-junit - 0.0.1-SNAPSHOT - pom - parallel-tests-junit - - - math-test-functions - string-test-functions - + 4.0.0 + com.baeldung + parallel-tests-junit + 0.0.1-SNAPSHOT + parallel-tests-junit + pom + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + math-test-functions + string-test-functions + + diff --git a/testing-modules/parallel-tests-junit/string-test-functions/pom.xml b/testing-modules/parallel-tests-junit/string-test-functions/pom.xml index af61cfce8e..b0c0ed29fc 100644 --- a/testing-modules/parallel-tests-junit/string-test-functions/pom.xml +++ b/testing-modules/parallel-tests-junit/string-test-functions/pom.xml @@ -4,26 +4,25 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 + string-test-functions + string-test-functions + http://maven.apache.org + com.baeldung parallel-tests-junit 0.0.1-SNAPSHOT - string-test-functions - string-test-functions - http://maven.apache.org - - UTF-8 - junit junit - 4.12 + ${junit.version} test + @@ -38,4 +37,8 @@ + + + UTF-8 + diff --git a/testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionTest.java b/testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionUnitTest.java similarity index 88% rename from testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionTest.java rename to testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionUnitTest.java index 7f2bc5e5e7..685a33b084 100644 --- a/testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionTest.java +++ b/testing-modules/parallel-tests-junit/string-test-functions/src/test/java/com/baeldung/StringFunctionUnitTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; -public class StringFunctionTest { +public class StringFunctionUnitTest { @Test public void test_upperCase() { diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml new file mode 100644 index 0000000000..bc6e23a6b7 --- /dev/null +++ b/testing-modules/pom.xml @@ -0,0 +1,39 @@ + + + 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 + junit-5-basics + easymock + junit-5-advanced + + diff --git a/testing-modules/rest-assured/README.md b/testing-modules/rest-assured/README.md index 50f36f61eb..ec108353a0 100644 --- a/testing-modules/rest-assured/README.md +++ b/testing-modules/rest-assured/README.md @@ -1,2 +1,5 @@ ###Relevant Articles: - [A Guide to REST-assured](http://www.baeldung.com/rest-assured-tutorial) +- [REST-assured Support for Spring MockMvc](https://www.baeldung.com/spring-mock-mvc-rest-assured) +- [Getting and Verifying Response Data with REST-assured](https://www.baeldung.com/rest-assured-response) +- [REST Assured Authentication](https://www.baeldung.com/rest-assured-authentication) diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index ed7e5e3577..4ed10f0641 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -8,16 +8,34 @@ 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-json + + + org.springframework.boot + spring-boot-starter-test + test + + + com.google.guava + guava + ${guava.version} + javax.servlet javax.servlet-api - ${javax.servlet-api.version} javax.servlet @@ -27,49 +45,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} @@ -93,18 +102,15 @@ joda-time joda-time - ${joda-time.version} com.fasterxml.jackson.core jackson-annotations - ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson.version} @@ -128,7 +134,6 @@ org.apache.httpcomponents httpclient - ${httpclient.version} @@ -142,17 +147,6 @@ wiremock ${wiremock.version} - - io.rest-assured - rest-assured - ${rest-assured.version} - test - - - io.rest-assured - json-schema-validator - ${rest-assured-json-schema-validator.version} - com.github.fge json-schema-validator @@ -168,14 +162,41 @@ commons-collections ${commons-collections.version} + + + org.springframework.boot + spring-boot-starter-security + + + + + io.rest-assured + rest-assured + test + + + io.rest-assured + spring-mock-mvc + test + + + io.rest-assured + json-schema-validator + test + + + com.github.scribejava + scribejava-apis + ${scribejava.version} + test + - 2.8.5 + 18.0 + 2.9.7 1.8 19.0 - - 3.1.0 2.5 1.4.7 9.4.0.v20161208 @@ -199,6 +220,8 @@ 3.0.1 3.0.1 + + 2.5.3 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/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/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/authentication/BasicAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicAuthenticationLiveTest.java new file mode 100644 index 0000000000..aff765dfa3 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicAuthenticationLiveTest.java @@ -0,0 +1,38 @@ +package com.baeldung.restassured.authentication; + +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.given; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; + +/** + * For this Live Test we need: + * * a running instance of the service located in the spring-security-rest-basic-auth module. + * @see spring-security-rest-basic-auth module + * + */ +public class BasicAuthenticationLiveTest { + + private static final String USER = "user1"; + private static final String PASSWORD = "user1Pass"; + private static final String SVC_URL = "http://localhost:8080/spring-security-rest-basic-auth/api/foos/1"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.UNAUTHORIZED.value()); + } + + @Test + public void givenBasicAuthentication_whenRequestSecuredResource_thenResourceRetrieved() { + given().auth() + .basic(USER, PASSWORD) + .when() + .get(SVC_URL) + .then() + .assertThat() + .statusCode(HttpStatus.OK.value()); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java new file mode 100644 index 0000000000..02138f22e3 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java @@ -0,0 +1,56 @@ +package com.baeldung.restassured.authentication; + +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; + +/** + * For this Live Test we need: + * * a running instance of the service located in the spring-boot-admin/spring-boot-admin-server module. + * @see spring-boot-admin/spring-boot-admin-server module + * + */ +public class BasicPreemtiveAuthenticationLiveTest { + + private static final String USER = "admin"; + private static final String PASSWORD = "admin"; + private static final String SVC_URL = "http://localhost:8080/api/applications/"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .content(containsString("spring-security-mvc-digest-auth module + * + */ +public class DigestAuthenticationLiveTest { + + private static final String USER = "user1"; + private static final String PASSWORD = "user1Pass"; + private static final String SVC_URL = "http://localhost:8080/spring-security-mvc-digest-auth/homepage.html"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.UNAUTHORIZED.value()); + } + + @Test + public void givenFormAuthentication_whenRequestSecuredResource_thenResourceRetrieved() { + given().auth() + .digest(USER, PASSWORD) + .when() + .get(SVC_URL) + .then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .content(containsString("This is the body of the sample view")); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/FormAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/FormAuthenticationLiveTest.java new file mode 100644 index 0000000000..66ae9fb162 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/FormAuthenticationLiveTest.java @@ -0,0 +1,57 @@ +package com.baeldung.restassured.authentication; + +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.isEmptyString; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; + +import io.restassured.authentication.FormAuthConfig; + +/** + * For this Live Test we need: + * * a running instance of the service located in the spring-security-mvc-login module. + * @see spring-security-mvc-login module + * + */ +public class FormAuthenticationLiveTest { + + private static final String USER = "user1"; + private static final String PASSWORD = "user1Pass"; + private static final String SVC_URL = "http://localhost:8080/spring-security-mvc-login/secured"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenLoginFormResponse() { + get(SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .content(containsString("spring-boot-admin/spring-boot-admin-server module + * + */ +public class FormAutoconfAuthenticationLiveTest { + + private static final String USER = "admin"; + private static final String PASSWORD = "admin"; + private static final String SVC_URL = "http://localhost:8080/ger1/api/applications/"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .content(containsString("spring-security-oauth/oauth-authorization-server module + * + * * a running instance of the service located in the spring-security-oauth repo - oauth-resource-server-1 module. + * @see spring-security-oauth/oauth-resource-server-1 module + * + */ +public class OAuth2AuthenticationLiveTest { + + private static final String USER = "john"; + private static final String PASSWORD = "123"; + private static final String CLIENT_ID = "fooClientIdPassword"; + private static final String SECRET = "secret"; + private static final String AUTH_SVC_TOKEN_URL = "http://localhost:8081/spring-security-oauth-server/oauth/token"; + private static final String RESOURCE_SVC_URL = "http://localhost:8082/spring-security-oauth-resource/foos/1"; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(RESOURCE_SVC_URL).then() + .assertThat() + .statusCode(HttpStatus.UNAUTHORIZED.value()); + } + + @Test + public void givenAccessTokenAuthentication_whenRequestSecuredResource_thenResourceRetrieved() { + String accessToken = given().auth() + .basic(CLIENT_ID, SECRET) + .formParam("grant_type", "password") + .formParam("username", USER) + .formParam("password", PASSWORD) + .formParam("scope", "read foo") + .when() + .post(AUTH_SVC_TOKEN_URL) + .then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .extract() + .path("access_token"); + + given().auth() + .oauth2(accessToken) + .when() + .get(RESOURCE_SVC_URL) + .then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .body("$", hasKey("id")) + .body("$", hasKey("name")); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/OAuthAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/OAuthAuthenticationLiveTest.java new file mode 100644 index 0000000000..c720bc04e4 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/OAuthAuthenticationLiveTest.java @@ -0,0 +1,53 @@ +package com.baeldung.restassured.authentication; + +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.hasKey; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; + +import io.restassured.http.ContentType; + +/** + * For this Live Test we need to obtain a valid Access Token and Token Secret: + * * start spring-mvc-simple application in debug mode + * @see spring-mvc-simple module + * * calling localhost:8080/spring-mvc-simple/twitter/authorization/ using the browser + * * debug the callback function where we can obtain the fields + */ +public class OAuthAuthenticationLiveTest { + + // We can obtain these two from the spring-mvc-simple / TwitterController class + private static final String OAUTH_API_KEY = "PSRszoHhRDVhyo2RIkThEbWko"; + private static final String OAUTH_API_SECRET = "prpJbz03DcGRN46sb4ucdSYtVxG8unUKhcnu3an5ItXbEOuenL"; + private static final String TWITTER_ENDPOINT = "https://api.twitter.com/1.1/account/settings.json"; + /* We can obtain the following by: + * - starting the spring-mvc-simple application + * - calling localhost:8080/spring-mvc-simple/twitter/authorization/ + * - debugging the callback function */ + private static final String ACCESS_TOKEN = "..."; + private static final String TOKEN_SECRET = "..."; + + @Test + public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() { + get(TWITTER_ENDPOINT).then() + .assertThat() + .statusCode(HttpStatus.BAD_REQUEST.value()); + } + + @Test + public void givenAccessTokenAuthentication_whenRequestSecuredResource_thenResourceIsRequested() { + given().accept(ContentType.JSON) + .auth() + .oauth(OAUTH_API_KEY, OAUTH_API_SECRET, ACCESS_TOKEN, TOKEN_SECRET) + .when() + .get(TWITTER_ENDPOINT) + .then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .body("$", hasKey("geo_enabled")) + .body("$", hasKey("language")); + } + +} 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..a55c0a69e4 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java @@ -0,0 +1,149 @@ +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", notNullValue()); + + Movie result = get(uri + "/movie/" + testMovie.getId()).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .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 + 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/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()); + } +} 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 diff --git a/testing-modules/rest-testing/README.md b/testing-modules/rest-testing/README.md index ab038807bc..2d366bd550 100644 --- a/testing-modules/rest-testing/README.md +++ b/testing-modules/rest-testing/README.md @@ -6,8 +6,8 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Test a REST API with Java](http://www.baeldung.com/integration-testing-a-rest-api) - [Introduction to WireMock](http://www.baeldung.com/introduction-to-wiremock) +- [Using WireMock Scenarios](https://www.baeldung.com/wiremock-scenarios) - [REST API Testing with Cucumber](http://www.baeldung.com/cucumber-rest-api-testing) - [Testing a REST API with JBehave](http://www.baeldung.com/jbehave-rest-testing) - [REST API Testing with Karate](http://www.baeldung.com/karate-rest-api-testing) diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index 9bfd715682..6dad3be117 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - com.baeldung rest-testing 0.1-SNAPSHOT @@ -150,9 +149,6 @@ - - 2.8.5 - 19.0 3.5 @@ -160,7 +156,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/WireMockScenarioExampleIntegrationTest.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java new file mode 100644 index 0000000000..946d3d717f --- /dev/null +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java @@ -0,0 +1,75 @@ +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.InputStreamReader; + +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 WireMockScenarioExampleIntegrationTest { + + 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(); + } + } + +} diff --git a/testing-modules/spring-testing/README.md b/testing-modules/spring-testing/README.md index 02ab7b24bd..0970eabeff 100644 --- a/testing-modules/spring-testing/README.md +++ b/testing-modules/spring-testing/README.md @@ -3,3 +3,6 @@ - [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) +- [Using SpringJUnit4ClassRunner with Parameterized](https://www.baeldung.com/springjunit4classrunner-parameterized) +- [Override properties in Spring]() diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index a137bc8d33..f4d7b5dc66 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -26,7 +26,6 @@ org.springframework.boot spring-boot-starter LATEST - test org.springframework.boot @@ -44,16 +43,38 @@ spring-context LATEST + + org.springframework + spring-webmvc + ${spring.version} + org.eclipse.persistence javax.persistence - 2.1.1 + ${javax.persistence.version} org.springframework.data spring-data-jpa LATEST + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.awaitility + awaitility + ${awaitility.version} + test + + + javax.servlet + javax.servlet-api + ${servlet.api.version} + @@ -70,6 +91,11 @@ 2.0.0.0 + 3.1.6 + 5.4.0 + 5.1.4.RELEASE + 4.0.1 + 2.1.1 \ No newline at end of file diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java new file mode 100644 index 0000000000..b54a2b5339 --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java @@ -0,0 +1,11 @@ +package com.baeldung.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling +@ComponentScan("com.baeldung.scheduled") +public class ScheduledConfig { +} diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java new file mode 100644 index 0000000000..eca0aed57f --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/config/WebConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import javax.servlet.ServletContext; + +@EnableWebMvc +@Configuration +@ComponentScan(basePackages = {"com.baeldung.controller.parameterized"}) +public class WebConfig { + + @Autowired + private ServletContext ctx; +} diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/controller/parameterized/EmployeeRoleController.java b/testing-modules/spring-testing/src/main/java/com/baeldung/controller/parameterized/EmployeeRoleController.java new file mode 100644 index 0000000000..0f1ed9e61d --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/controller/parameterized/EmployeeRoleController.java @@ -0,0 +1,32 @@ +package com.baeldung.controller.parameterized; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.HashMap; +import java.util.Map; + +@Controller +public class EmployeeRoleController { + + private static Map userRoleCache = new HashMap<>(); + + static { + userRoleCache.put("John", Role.ADMIN); + userRoleCache.put("Doe", Role.EMPLOYEE); + } + + @RequestMapping(value = "/role/{name}", method = RequestMethod.GET, produces = "application/text") + @ResponseBody + public String getEmployeeRole(@PathVariable("name") String employeeName) { + + return userRoleCache.get(employeeName).toString(); + } + + private enum Role { + ADMIN, EMPLOYEE + } +} diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/overrideproperties/Application.java b/testing-modules/spring-testing/src/main/java/com/baeldung/overrideproperties/Application.java new file mode 100644 index 0000000000..ac215bf78e --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/overrideproperties/Application.java @@ -0,0 +1,11 @@ +package com.baeldung.overrideproperties; + +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/spring-testing/src/main/java/com/baeldung/overrideproperties/resolver/PropertySourceResolver.java b/testing-modules/spring-testing/src/main/java/com/baeldung/overrideproperties/resolver/PropertySourceResolver.java new file mode 100644 index 0000000000..074092b7df --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/overrideproperties/resolver/PropertySourceResolver.java @@ -0,0 +1,24 @@ +package com.baeldung.overrideproperties.resolver; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class PropertySourceResolver { + + private final String firstProperty; + private final String secondProperty; + + public PropertySourceResolver(@Value("${example.firstProperty}") String firstProperty, @Value("${example.secondProperty}") String secondProperty) { + this.firstProperty = firstProperty; + this.secondProperty = secondProperty; + } + + public String getFirstProperty() { + return firstProperty; + } + + public String getSecondProperty() { + return secondProperty; + } +} diff --git a/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java b/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java new file mode 100644 index 0000000000..17aa15b6f3 --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java @@ -0,0 +1,20 @@ +package com.baeldung.scheduled; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.concurrent.atomic.AtomicInteger; + +@Component +public class Counter { + private final AtomicInteger count = new AtomicInteger(0); + + @Scheduled(fixedDelay = 5) + public void scheduled() { + this.count.incrementAndGet(); + } + + public int getInvocationCount() { + return this.count.get(); + } +} diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerIntegrationTest.java new file mode 100644 index 0000000000..c362067cc0 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerIntegrationTest.java @@ -0,0 +1,49 @@ +package com.baeldung.controller.parameterized; + +import com.baeldung.config.WebConfig; +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.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class RoleControllerIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + private static final String CONTENT_TYPE = "application/text;charset=ISO-8859-1"; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenEmployeeNameJohnWhenInvokeRoleThenReturnAdmin() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/role/John")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.content().string("ADMIN")); + } + + @Test + public void givenEmployeeNameDoeWhenInvokeRoleThenReturnEmployee() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/role/Doe")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.content().string("EMPLOYEE")); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedClassRuleIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedClassRuleIntegrationTest.java new file mode 100644 index 0000000000..eca294a742 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedClassRuleIntegrationTest.java @@ -0,0 +1,73 @@ +package com.baeldung.controller.parameterized; + +import com.baeldung.config.WebConfig; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestContextManager; +import org.springframework.test.context.junit4.rules.SpringClassRule; +import org.springframework.test.context.junit4.rules.SpringMethodRule; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.util.ArrayList; +import java.util.Collection; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +@RunWith(Parameterized.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class RoleControllerParameterizedClassRuleIntegrationTest { + + private static final String CONTENT_TYPE = "application/text;charset=ISO-8859-1"; + + @ClassRule + public static final SpringClassRule scr = new SpringClassRule(); + + @Rule + public final SpringMethodRule smr = new SpringMethodRule(); + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Parameter(value = 0) + public String name; + + @Parameter(value = 1) + public String role; + + @Parameters + public static Collection data() { + Collection params = new ArrayList(); + params.add(new Object[]{"John", "ADMIN"}); + params.add(new Object[]{"Doe", "EMPLOYEE"}); + + return params; + } + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenEmployeeNameWhenInvokeRoleThenReturnRole() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/role/" + name)).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.content().string(role)); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedIntegrationTest.java new file mode 100644 index 0000000000..1458b24b06 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/controller/parameterized/RoleControllerParameterizedIntegrationTest.java @@ -0,0 +1,69 @@ +package com.baeldung.controller.parameterized; + +import com.baeldung.config.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestContextManager; +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.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.util.ArrayList; +import java.util.Collection; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +@RunWith(Parameterized.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class RoleControllerParameterizedIntegrationTest { + + private static final String CONTENT_TYPE = "application/text;charset=ISO-8859-1"; + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + private TestContextManager testContextManager; + + @Parameter(value = 0) + public String name; + + @Parameter(value = 1) + public String role; + + @Parameters + public static Collection data() { + Collection params = new ArrayList(); + params.add(new Object[]{"John", "ADMIN"}); + params.add(new Object[]{"Doe", "EMPLOYEE"}); + + return params; + } + + @Before + public void setup() throws Exception { + this.testContextManager = new TestContextManager(getClass()); + this.testContextManager.prepareTestInstance(this); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenEmployeeNameWhenInvokeRoleThenReturnRole() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/role/" + name)).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.content().string(role)); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ContextPropertySourceResolverIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ContextPropertySourceResolverIntegrationTest.java new file mode 100644 index 0000000000..9b692edd7b --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ContextPropertySourceResolverIntegrationTest.java @@ -0,0 +1,27 @@ +package com.baeldung.overrideproperties; + +import com.baeldung.overrideproperties.resolver.PropertySourceResolver; +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.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@ContextConfiguration(initializers = PropertyOverrideContextInitializer.class, classes = Application.class) +public class ContextPropertySourceResolverIntegrationTest { + + @Autowired private PropertySourceResolver propertySourceResolver; + + @Test + public void shouldContext_overridePropertyValues() { + final String firstProperty = propertySourceResolver.getFirstProperty(); + final String secondProperty = propertySourceResolver.getSecondProperty(); + + assertEquals(PropertyOverrideContextInitializer.PROPERTY_FIRST_VALUE, firstProperty); + assertEquals("contextFile", secondProperty); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ProfilePropertySourceResolverIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ProfilePropertySourceResolverIntegrationTest.java new file mode 100644 index 0000000000..95d83420b7 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/ProfilePropertySourceResolverIntegrationTest.java @@ -0,0 +1,29 @@ +package com.baeldung.overrideproperties; + +import com.baeldung.overrideproperties.resolver.PropertySourceResolver; +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.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles("test") +public class ProfilePropertySourceResolverIntegrationTest { + + @Autowired private PropertySourceResolver propertySourceResolver; + + @Test + public void shouldProfiledProperty_overridePropertyValues() { + final String firstProperty = propertySourceResolver.getFirstProperty(); + final String secondProperty = propertySourceResolver.getSecondProperty(); + + assertEquals("profile", firstProperty); + assertEquals("file", secondProperty); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/PropertyOverrideContextInitializer.java b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/PropertyOverrideContextInitializer.java new file mode 100644 index 0000000000..a8c4267c5c --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/PropertyOverrideContextInitializer.java @@ -0,0 +1,17 @@ +package com.baeldung.overrideproperties; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.support.TestPropertySourceUtils; + +public class PropertyOverrideContextInitializer implements ApplicationContextInitializer { + + static final String PROPERTY_FIRST_VALUE = "contextClass"; + + @Override + public void initialize(ConfigurableApplicationContext configurableApplicationContext) { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, "example.firstProperty=" + PROPERTY_FIRST_VALUE); + + TestPropertySourceUtils.addPropertiesFilesToEnvironment(configurableApplicationContext, "context-override-application.properties"); + } +} diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/SpringBootPropertySourceResolverIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/SpringBootPropertySourceResolverIntegrationTest.java new file mode 100644 index 0000000000..573a46dd5f --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/SpringBootPropertySourceResolverIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.overrideproperties; + +import com.baeldung.overrideproperties.resolver.PropertySourceResolver; +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; + +@RunWith(SpringRunner.class) +@SpringBootTest(properties = { "example.firstProperty=annotation" }) +public class SpringBootPropertySourceResolverIntegrationTest { + + @Autowired private PropertySourceResolver propertySourceResolver; + + @Test + public void shouldSpringBootTestAnnotation_overridePropertyValues() { + final String firstProperty = propertySourceResolver.getFirstProperty(); + final String secondProperty = propertySourceResolver.getSecondProperty(); + + Assert.assertEquals("annotation", firstProperty); + Assert.assertEquals("file", secondProperty); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/TestResourcePropertySourceResolverIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/TestResourcePropertySourceResolverIntegrationTest.java new file mode 100644 index 0000000000..c724713854 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/overrideproperties/TestResourcePropertySourceResolverIntegrationTest.java @@ -0,0 +1,27 @@ +package com.baeldung.overrideproperties; + +import com.baeldung.overrideproperties.resolver.PropertySourceResolver; +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 static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestResourcePropertySourceResolverIntegrationTest { + + @Autowired private PropertySourceResolver propertySourceResolver; + + @Test + public void shouldTestResourceFile_overridePropertyValues() { + final String firstProperty = propertySourceResolver.getFirstProperty(); + final String secondProperty = propertySourceResolver.getSecondProperty(); + + assertEquals("file", firstProperty); + assertEquals("file", secondProperty); + } + +} \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java new file mode 100644 index 0000000000..4883aa16c2 --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java @@ -0,0 +1,24 @@ +package com.baeldung.scheduled; + +import com.baeldung.config.ScheduledConfig; +import org.awaitility.Duration; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.awaitility.Awaitility.await; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.verify; + +@SpringJUnitConfig(ScheduledConfig.class) +public class ScheduledAwaitilityIntegrationTest { + + @SpyBean private Counter counter; + + @Test + public void whenWaitOneSecond_thenScheduledIsCalledAtLeastTenTimes() { + await() + .atMost(Duration.ONE_SECOND) + .untilAsserted(() -> verify(counter, atLeast(10)).scheduled()); + } +} diff --git a/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java new file mode 100644 index 0000000000..058cd50caa --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java @@ -0,0 +1,22 @@ +package com.baeldung.scheduled; + +import com.baeldung.config.ScheduledConfig; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(ScheduledConfig.class) +public class ScheduledIntegrationTest { + + @Autowired Counter counter; + + @Test + public void givenSleepBy100ms_whenGetInvocationCount_thenIsGreaterThanZero() throws InterruptedException { + Thread.sleep(100L); + + assertThat(counter.getInvocationCount()).isGreaterThan(0); + } + +} diff --git a/testing-modules/spring-testing/src/test/resources/application-test.properties b/testing-modules/spring-testing/src/test/resources/application-test.properties new file mode 100644 index 0000000000..54c5bda7e8 --- /dev/null +++ b/testing-modules/spring-testing/src/test/resources/application-test.properties @@ -0,0 +1,2 @@ +# override properties +example.firstProperty=profile \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/resources/application.properties b/testing-modules/spring-testing/src/test/resources/application.properties new file mode 100644 index 0000000000..6c74aa2995 --- /dev/null +++ b/testing-modules/spring-testing/src/test/resources/application.properties @@ -0,0 +1,3 @@ +# override properties +example.firstProperty=file +example.secondProperty=file \ No newline at end of file diff --git a/testing-modules/spring-testing/src/test/resources/context-override-application.properties b/testing-modules/spring-testing/src/test/resources/context-override-application.properties new file mode 100644 index 0000000000..c39e5d3966 --- /dev/null +++ b/testing-modules/spring-testing/src/test/resources/context-override-application.properties @@ -0,0 +1 @@ +example.secondProperty=contextFile \ No newline at end of file diff --git a/testing-modules/test-containers/pom.xml b/testing-modules/test-containers/pom.xml index 1f4c483988..7ee002ea8b 100644 --- a/testing-modules/test-containers/pom.xml +++ b/testing-modules/test-containers/pom.xml @@ -103,7 +103,6 @@ 1.0.1 4.12.1 2.8.2 - 1.4.196 2.21.0 5.0.1.RELEASE 1.7.2 diff --git a/testing-modules/testing/README.md b/testing-modules/testing/README.md index 849b578a55..4a7829e867 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) @@ -18,6 +18,6 @@ - [Custom JUnit 4 Test Runners](http://www.baeldung.com/junit-4-custom-runners) - [Guide to JSpec](http://www.baeldung.com/jspec) - [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion) -- [Using Conditions with AssertJ](http://www.baeldung.com/assertj-conditions) -- [Guide to JavaFaker](https://www.baeldung.com/java-faker) +- [Using Conditions with AssertJ Assertions](http://www.baeldung.com/assertj-conditions) +- [A Guide to JavaFaker](https://www.baeldung.com/java-faker) - [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java) diff --git a/testing-modules/testing/pom.xml b/testing-modules/testing/pom.xml index 2e783b2116..ccfa1070d1 100644 --- a/testing-modules/testing/pom.xml +++ b/testing-modules/testing/pom.xml @@ -91,7 +91,7 @@ com.github.javafaker javafaker - 0.15 + ${javafaker.version} @@ -177,6 +177,7 @@ 0.4 3.0.0 1.5 + 0.15 diff --git a/testing-modules/testng/pom.xml b/testing-modules/testng/pom.xml index a9f680aafb..8389604717 100644 --- a/testing-modules/testng/pom.xml +++ b/testing-modules/testng/pom.xml @@ -4,8 +4,8 @@ 4.0.0 testng 0.1.0-SNAPSHOT - jar testng + jar com.baeldung diff --git a/twilio/pom.xml b/twilio/pom.xml index 81fbf8ab20..266ac45c92 100644 --- a/twilio/pom.xml +++ b/twilio/pom.xml @@ -16,8 +16,12 @@ com.twilio.sdk twilio - 7.20.0 + ${twilio.version} + + 7.20.0 + + diff --git a/undertow/pom.xml b/undertow/pom.xml index d000956aee..1c2cc3aa36 100644 --- a/undertow/pom.xml +++ b/undertow/pom.xml @@ -1,12 +1,11 @@ 4.0.0 - com.baeldung.undertow undertow - jar 1.0-SNAPSHOT undertow + jar http://maven.apache.org diff --git a/vaadin/pom.xml b/vaadin/pom.xml index c34ffa3636..089ebe67c1 100644 --- a/vaadin/pom.xml +++ b/vaadin/pom.xml @@ -2,12 +2,11 @@ 4.0.0 - org.test vaadin - war 1.0-SNAPSHOT Vaadin + war parent-boot-2 @@ -37,20 +36,23 @@ com.vaadin vaadin-server + ${vaadin-server.version} com.vaadin vaadin-push + ${vaadin-push.version} com.vaadin vaadin-client-compiled + ${vaadin-client-compiled.version} com.vaadin vaadin-themes + ${vaadin-themes.version} - org.springframework.boot spring-boot-starter-data-jpa @@ -87,17 +89,6 @@ com.vaadin vaadin-maven-plugin ${vaadin.plugin.version} - - - - update-theme - update-widgetset - compile - - compile-theme - - - org.apache.maven.plugins @@ -183,10 +174,13 @@ - 3.0.1 - 7.7.10 - 8.0.6 - 10.0.1 + 13.0.9 + 13.0.9 + 13.0.9 + 8.8.5 + 8.8.5 + 8.8.5 + 8.8.5 9.3.9.v20160517 UTF-8 1.8 diff --git a/vaadin/src/main/java/com/baeldung/introduction/VaadinUI.java b/vaadin/src/main/java/com/baeldung/introduction/VaadinUI.java index 1b3733ad74..68be53b1b3 100644 --- a/vaadin/src/main/java/com/baeldung/introduction/VaadinUI.java +++ b/vaadin/src/main/java/com/baeldung/introduction/VaadinUI.java @@ -1,8 +1,8 @@ package com.baeldung.introduction; import java.time.Instant; +import java.time.LocalDate; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -13,11 +13,10 @@ import javax.servlet.annotation.WebServlet; import com.vaadin.annotations.Push; import com.vaadin.annotations.Theme; import com.vaadin.annotations.VaadinServletConfiguration; -import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.data.Binder; import com.vaadin.data.validator.StringLengthValidator; +import com.vaadin.icons.VaadinIcons; import com.vaadin.server.ExternalResource; -import com.vaadin.server.FontAwesome; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinServlet; import com.vaadin.ui.Button; @@ -84,7 +83,7 @@ public class VaadinUI extends UI { textField.setId("TextField"); textField.setCaption("TextField:"); textField.setValue("TextField Value"); - textField.setIcon(FontAwesome.USER); + textField.setIcon(VaadinIcons.USER); gridLayout.addComponent(textField); final TextArea textArea = new TextArea(); @@ -93,7 +92,7 @@ public class VaadinUI extends UI { textArea.setValue("TextArea Value"); gridLayout.addComponent(textArea); - final DateField dateField = new DateField("DateField", new Date(0)); + final DateField dateField = new DateField("DateField", LocalDate.ofEpochDay(0)); dateField.setId("DateField"); gridLayout.addComponent(dateField); @@ -112,7 +111,7 @@ public class VaadinUI extends UI { richTextPanel.setContent(richTextArea); final InlineDateField inlineDateField = new InlineDateField(); - inlineDateField.setValue(new Date(0)); + inlineDateField.setValue(LocalDate.ofEpochDay(0)); inlineDateField.setCaption("Inline Date Field"); horizontalLayout.addComponent(inlineDateField); @@ -160,7 +159,7 @@ public class VaadinUI extends UI { buttonLayout.addComponent(nativeButton); Button iconButton = new Button("Icon Button"); - iconButton.setIcon(FontAwesome.ALIGN_LEFT); + iconButton.setIcon(VaadinIcons.ALIGN_LEFT); buttonLayout.addComponent(iconButton); Button borderlessButton = new Button("BorderLess Button"); @@ -187,25 +186,25 @@ public class VaadinUI extends UI { numbers.add("Ten"); numbers.add("Eleven"); ComboBox comboBox = new ComboBox("ComboBox"); - comboBox.addItems(numbers); + comboBox.setItems(numbers); formLayout.addComponent(comboBox); ListSelect listSelect = new ListSelect("ListSelect"); - listSelect.addItems(numbers); + listSelect.setItems(numbers); listSelect.setRows(2); formLayout.addComponent(listSelect); NativeSelect nativeSelect = new NativeSelect("NativeSelect"); - nativeSelect.addItems(numbers); + nativeSelect.setItems(numbers); formLayout.addComponent(nativeSelect); TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect"); - twinColSelect.addItems(numbers); + twinColSelect.setItems(numbers); Grid grid = new Grid("Grid"); grid.setColumns("Column1", "Column2", "Column3"); - grid.addRow("Item1", "Item2", "Item3"); - grid.addRow("Item4", "Item5", "Item6"); + grid.setItems("Item1", "Item2", "Item3"); + grid.setItems("Item4", "Item5", "Item6"); Panel panel = new Panel("Panel"); panel.setContent(grid); @@ -229,11 +228,12 @@ public class VaadinUI extends UI { dataBindingLayout.setSpacing(true); dataBindingLayout.setMargin(true); + Binder binder = new Binder<>(); BindData bindData = new BindData("BindData"); - BeanFieldGroup beanFieldGroup = new BeanFieldGroup(BindData.class); - beanFieldGroup.setItemDataSource(bindData); - TextField bindedTextField = (TextField) beanFieldGroup.buildAndBind("BindName", "bindName"); + binder.readBean(bindData); + TextField bindedTextField = new TextField(); bindedTextField.setWidth("250px"); + binder.forField(bindedTextField).bind(BindData::getBindName, BindData::setBindName); dataBindingLayout.addComponent(bindedTextField); FormLayout validatorLayout = new FormLayout(); @@ -244,21 +244,18 @@ public class VaadinUI extends UI { textValidatorLayout.setSpacing(true); textValidatorLayout.setMargin(true); + + BindData stringValidatorBindData = new BindData(""); TextField stringValidator = new TextField(); - stringValidator.setNullSettingAllowed(true); - stringValidator.setNullRepresentation(""); - stringValidator.addValidator(new StringLengthValidator("String must have 2-5 characters lenght", 2, 5, true)); - stringValidator.setValidationVisible(false); + Binder stringValidatorBinder = new Binder<>(); + stringValidatorBinder.setBean(stringValidatorBindData); + stringValidatorBinder.forField(stringValidator) + .withValidator(new StringLengthValidator("String must have 2-5 characters lenght", 2, 5)) + .bind(BindData::getBindName, BindData::setBindName); + textValidatorLayout.addComponent(stringValidator); Button buttonStringValidator = new Button("Validate String"); - buttonStringValidator.addClickListener(e -> { - try { - stringValidator.setValidationVisible(false); - stringValidator.validate(); - } catch (InvalidValueException err) { - stringValidator.setValidationVisible(true); - } - }); + buttonStringValidator.addClickListener(e -> stringValidatorBinder.validate()); textValidatorLayout.addComponent(buttonStringValidator); validatorLayout.addComponent(textValidatorLayout); @@ -278,4 +275,4 @@ public class VaadinUI extends UI { @VaadinServletConfiguration(ui = VaadinUI.class, productionMode = false) public static class MyUIServlet extends VaadinServlet { } -} +} \ No newline at end of file diff --git a/vavr/README.md b/vavr/README.md index b7ba72229b..266cae91bb 100644 --- a/vavr/README.md +++ b/vavr/README.md @@ -4,11 +4,10 @@ - [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) - [Introduction to Future in Vavr](http://www.baeldung.com/vavr-future) -- [Introduction to VRaptor in Java](http://www.baeldung.com/vraptor) - [Introduction to Vavr’s Either](http://www.baeldung.com/vavr-either) - [Interoperability Between Java and Vavr](http://www.baeldung.com/java-vavr) diff --git a/vavr/pom.xml b/vavr/pom.xml index ae495e9830..a2c6e29cde 100644 --- a/vavr/pom.xml +++ b/vavr/pom.xml @@ -41,7 +41,6 @@ - 1.8 0.9.1 3.0.0 diff --git a/vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/application/Application.java b/vavr/src/main/java/com/baeldung/vavrvalidation/application/Application.java similarity index 95% rename from vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/application/Application.java rename to vavr/src/main/java/com/baeldung/vavrvalidation/application/Application.java index 8acc4522af..a23ed185c8 100644 --- a/vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/application/Application.java +++ b/vavr/src/main/java/com/baeldung/vavrvalidation/application/Application.java @@ -8,10 +8,10 @@ import io.vavr.control.Validation; public class Application { public static void main(String[] args) { - + UserValidator userValidator = new UserValidator(); Validation, User> validation = userValidator.validateUser("John", "john@domain.com"); - + // process validation results here - } + } } diff --git a/vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/model/User.java b/vavr/src/main/java/com/baeldung/vavrvalidation/model/User.java similarity index 100% rename from vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/model/User.java rename to vavr/src/main/java/com/baeldung/vavrvalidation/model/User.java diff --git a/vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/validator/UserValidator.java b/vavr/src/main/java/com/baeldung/vavrvalidation/validator/UserValidator.java similarity index 100% rename from vavr/vavr-validation/src/main/java/com/baeldung/vavrvalidation/validator/UserValidator.java rename to vavr/src/main/java/com/baeldung/vavrvalidation/validator/UserValidator.java diff --git a/vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorTest.java b/vavr/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorUnitTest.java similarity index 95% rename from vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorTest.java rename to vavr/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorUnitTest.java index cb9557fa53..8ac6100b27 100644 --- a/vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorTest.java +++ b/vavr/src/test/java/com/baeldung/vavrvalidation/validator/UserValidatorUnitTest.java @@ -7,7 +7,7 @@ import com.baeldung.vavrvalidation.validator.UserValidator; import io.vavr.control.Validation.Invalid; import io.vavr.control.Validation.Valid; -public class UserValidatorTest { +public class UserValidatorUnitTest { @Test public void givenValidUserParams_whenValidated_thenInstanceOfValid() { diff --git a/vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/ValidationTest.java b/vavr/src/test/java/com/baeldung/vavrvalidation/validator/ValidationUnitTest.java similarity index 98% rename from vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/ValidationTest.java rename to vavr/src/test/java/com/baeldung/vavrvalidation/validator/ValidationUnitTest.java index c89b43b5e3..7b8c551aeb 100644 --- a/vavr/vavr-validation/src/test/java/com/baeldung/vavrvalidation/validator/ValidationTest.java +++ b/vavr/src/test/java/com/baeldung/vavrvalidation/validator/ValidationUnitTest.java @@ -11,7 +11,7 @@ import io.vavr.control.Either.Right; import io.vavr.control.Validation.Invalid; import io.vavr.control.Validation.Valid; -public class ValidationTest { +public class ValidationUnitTest { private static UserValidator userValidator; diff --git a/vertx-and-rxjava/.gitignore b/vertx-and-rxjava/.gitignore new file mode 100644 index 0000000000..3aba11e2fd --- /dev/null +++ b/vertx-and-rxjava/.gitignore @@ -0,0 +1 @@ +/.vertx \ No newline at end of file diff --git a/vertx/pom.xml b/vertx/pom.xml index 7e494c5914..befd4c45bb 100644 --- a/vertx/pom.xml +++ b/vertx/pom.xml @@ -2,7 +2,6 @@ 4.0.0 - com.baeldung vertx 1.0-SNAPSHOT diff --git a/video-tutorials/jackson-annotations/pom.xml b/video-tutorials/jackson-annotations/pom.xml index 121609ad4d..2492951d1a 100644 --- a/video-tutorials/jackson-annotations/pom.xml +++ b/video-tutorials/jackson-annotations/pom.xml @@ -136,10 +136,6 @@ - - - 2.8.5 - 2.9.6 2.8.0 diff --git a/video-tutorials/pom.xml b/video-tutorials/pom.xml index ca3b39904f..a798f77863 100644 --- a/video-tutorials/pom.xml +++ b/video-tutorials/pom.xml @@ -1,12 +1,11 @@ 4.0.0 - com.baeldung video-tutorials 1.0.0-SNAPSHOT - pom video-tutorials + pom com.baeldung diff --git a/vraptor/pom.xml b/vraptor/pom.xml index 97005bd158..3904eb8c63 100644 --- a/vraptor/pom.xml +++ b/vraptor/pom.xml @@ -4,8 +4,8 @@ com.baeldung vraptor 1.0.0 - war vraptor + war A demo project to start using VRaptor 4 @@ -67,7 +67,7 @@ javax.servlet javax.servlet-api - ${servlet.version} + ${javax.servlet-api.version} provided @@ -129,8 +129,6 @@ 2.1.2.Final 2.2 5.1.1.Final - 1.2 - 3.1.0 1.7.5 4.1.0-RC3 4.0.4 diff --git a/wicket/pom.xml b/wicket/pom.xml index 99be467167..80c728e3a5 100644 --- a/wicket/pom.xml +++ b/wicket/pom.xml @@ -2,12 +2,11 @@ 4.0.0 - com.baeldung.wicket.examples wicket - war 1.0-SNAPSHOT Wicket + war com.baeldung diff --git a/xml/pom.xml b/xml/pom.xml index 5490f3a89f..e9b89c71fc 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -24,13 +24,28 @@ ${jaxen.version} - org.jdom jdom2 ${jdom2.version} + + javax.xml + jaxb-api + ${jaxb-api.version} + + + javax.xml + jaxp-api + ${jaxp-api.version} + + + javax.xml.stream + stax-api + ${stax-api.version} + + commons-io @@ -166,7 +181,7 @@ template-binding.xml - src/main/resources + src/main/resources *-binding.xml @@ -174,14 +189,14 @@
- process-classes + process-classes process-classes bind - - process-test-classes + + process-test-classes process-test-classes test-bind @@ -230,34 +245,6 @@ - - - jibx.sf.net - JiBX repository - http://jibx.sf.net/maven2 - - never - - - false - - - - - - - jibx.sf.net - JiBX repository - http://jibx.sf.net/maven2 - - never - - - false - - - - 1.6.1 1.1.6 @@ -265,6 +252,9 @@ 2.5 4.1 1.2.4.5 + 2.1 + 1.4.2 + 1.0-2 3.5 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 diff --git a/xmlunit-2/pom.xml b/xmlunit-2/pom.xml index faefeca7a1..9e146ccf33 100644 --- a/xmlunit-2/pom.xml +++ b/xmlunit-2/pom.xml @@ -23,7 +23,6 @@ xmlunit-core ${xmlunit.version} - diff --git a/xstream/pom.xml b/xstream/pom.xml index 64c8198082..f75e10fc7d 100644 --- a/xstream/pom.xml +++ b/xstream/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - org.baeldung xstream 0.0.1-SNAPSHOT