merge with base repo
This commit is contained in:
commit
0568de3d94
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.algorithms.prime;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class PrimeGenerator {
|
||||||
|
public static List<Integer> sieveOfEratosthenes(int n) {
|
||||||
|
final boolean prime[] = new boolean[n + 1];
|
||||||
|
Arrays.fill(prime, true);
|
||||||
|
|
||||||
|
for (int p = 2; p * p <= n; p++) {
|
||||||
|
if (prime[p]) {
|
||||||
|
for (int i = p * 2; i <= n; i += p)
|
||||||
|
prime[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Integer> primes = new LinkedList<>();
|
||||||
|
for (int i = 2; i <= n; i++) {
|
||||||
|
if (prime[i])
|
||||||
|
primes.add(i);
|
||||||
|
}
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersBruteForce(int max) {
|
||||||
|
final List<Integer> primeNumbers = new LinkedList<Integer>();
|
||||||
|
for (int i = 2; i <= max; i++) {
|
||||||
|
if (isPrimeBruteForce(i)) {
|
||||||
|
primeNumbers.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primeNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrimeBruteForce(int x) {
|
||||||
|
for (int i = 2; i < x; i++) {
|
||||||
|
if (x % i == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersTill(int max) {
|
||||||
|
return IntStream.rangeClosed(2, max)
|
||||||
|
.filter(x -> isPrime(x))
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrime(int x) {
|
||||||
|
return IntStream.rangeClosed(2, (int) (Math.sqrt(x)))
|
||||||
|
.allMatch(n -> x % n != 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.algorithms.prime;
|
||||||
|
|
||||||
|
import static com.baeldung.algorithms.prime.PrimeGenerator.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PrimeGeneratorTest {
|
||||||
|
@Test
|
||||||
|
public void whenBruteForced_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersBruteForce(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOptimized_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersTill(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSieveOfEratosthenes_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = sieveOfEratosthenes(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
## Relevant articles:
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,27 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
||||||
|
/.mvn/
|
||||||
|
/mvnw
|
||||||
|
/mvnw.cmd
|
|
@ -106,75 +106,5 @@
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>integration</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*LiveTest.java</exclude>
|
|
||||||
<exclude>**/AutoconfigurationTest.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
<includes>
|
|
||||||
<include>**/*IntegrationTest.java</include>
|
|
||||||
</includes>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<test.mime>json</test.mime>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>autoconfiguration</id>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>integration-test</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<excludes>
|
|
||||||
<exclude>**/*LiveTest.java</exclude>
|
|
||||||
<exclude>**/*IntegrationTest.java</exclude>
|
|
||||||
</excludes>
|
|
||||||
<includes>
|
|
||||||
<include>**/AutoconfigurationTest.java</include>
|
|
||||||
</includes>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<systemPropertyVariables>
|
|
||||||
<test.mime>json</test.mime>
|
|
||||||
</systemPropertyVariables>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -40,14 +40,14 @@ public class CasSecuredAppApplication {
|
||||||
@Primary
|
@Primary
|
||||||
public AuthenticationEntryPoint authenticationEntryPoint(ServiceProperties sP) {
|
public AuthenticationEntryPoint authenticationEntryPoint(ServiceProperties sP) {
|
||||||
CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
|
CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
|
||||||
entryPoint.setLoginUrl("https://localhost:8443/cas/login");
|
entryPoint.setLoginUrl("https://localhost:6443/cas/login");
|
||||||
entryPoint.setServiceProperties(sP);
|
entryPoint.setServiceProperties(sP);
|
||||||
return entryPoint;
|
return entryPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TicketValidator ticketValidator() {
|
public TicketValidator ticketValidator() {
|
||||||
return new Cas30ServiceTicketValidator("https://localhost:8443/cas");
|
return new Cas30ServiceTicketValidator("https://localhost:6443/cas");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -71,7 +71,7 @@ public class CasSecuredAppApplication {
|
||||||
@Bean
|
@Bean
|
||||||
public LogoutFilter logoutFilter() {
|
public LogoutFilter logoutFilter() {
|
||||||
LogoutFilter logoutFilter = new LogoutFilter(
|
LogoutFilter logoutFilter = new LogoutFilter(
|
||||||
"https://localhost:8443/cas/logout", securityContextLogoutHandler());
|
"https://localhost:6443/cas/logout", securityContextLogoutHandler());
|
||||||
logoutFilter.setFilterProcessesUrl("/logout/cas");
|
logoutFilter.setFilterProcessesUrl("/logout/cas");
|
||||||
return logoutFilter;
|
return logoutFilter;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public class CasSecuredAppApplication {
|
||||||
@Bean
|
@Bean
|
||||||
public SingleSignOutFilter singleSignOutFilter() {
|
public SingleSignOutFilter singleSignOutFilter() {
|
||||||
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
|
SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
|
||||||
singleSignOutFilter.setCasServerUrlPrefix("https://localhost:8443/cas");
|
singleSignOutFilter.setCasServerUrlPrefix("https://localhost:6443/cas");
|
||||||
singleSignOutFilter.setIgnoreInitConfiguration(true);
|
singleSignOutFilter.setIgnoreInitConfiguration(true);
|
||||||
return singleSignOutFilter;
|
return singleSignOutFilter;
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
public class CasSecuredAppApplicationIntegrationTest {
|
public class CasSecuredAppApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contextLoads() {
|
public void contextLoads() {
|
|
@ -2,9 +2,9 @@
|
||||||
# CAS Server Context Configuration
|
# CAS Server Context Configuration
|
||||||
#
|
#
|
||||||
server.context-path=/cas
|
server.context-path=/cas
|
||||||
server.port=8443
|
server.port=6443
|
||||||
|
|
||||||
server.ssl.key-store=file:/etc/cas/thekeystore
|
server.ssl.key-store=classpath:/etc/cas/thekeystore
|
||||||
server.ssl.key-store-password=changeit
|
server.ssl.key-store-password=changeit
|
||||||
server.ssl.key-password=changeit
|
server.ssl.key-password=changeit
|
||||||
# server.ssl.ciphers=
|
# server.ssl.ciphers=
|
||||||
|
@ -40,6 +40,12 @@ spring.http.encoding.charset=UTF-8
|
||||||
spring.http.encoding.enabled=true
|
spring.http.encoding.enabled=true
|
||||||
spring.http.encoding.force=true
|
spring.http.encoding.force=true
|
||||||
|
|
||||||
|
##
|
||||||
|
#CAS CONFIG LOCATION
|
||||||
|
#
|
||||||
|
cas.standalone.config=classpath:/etc/cas/config
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# CAS Cloud Bus Configuration
|
# CAS Cloud Bus Configuration
|
||||||
#
|
#
|
||||||
|
@ -82,6 +88,7 @@ spring.thymeleaf.mode=HTML
|
||||||
# CAS Log4j Configuration
|
# CAS Log4j Configuration
|
||||||
#
|
#
|
||||||
# logging.config=file:/etc/cas/log4j2.xml
|
# logging.config=file:/etc/cas/log4j2.xml
|
||||||
|
|
||||||
server.context-parameters.isLog4jAutoInitializationDisabled=true
|
server.context-parameters.isLog4jAutoInitializationDisabled=true
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -104,9 +111,10 @@ cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
|
||||||
cas.authn.jdbc.query[0].user=root
|
cas.authn.jdbc.query[0].user=root
|
||||||
cas.authn.jdbc.query[0].password=
|
cas.authn.jdbc.query[0].password=
|
||||||
cas.authn.jdbc.query[0].ddlAuto=none
|
cas.authn.jdbc.query[0].ddlAuto=none
|
||||||
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
|
#cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
|
||||||
|
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver
|
||||||
cas.authn.jdbc.query[0].fieldPassword=password
|
cas.authn.jdbc.query[0].fieldPassword=password
|
||||||
cas.authn.jdbc.query[0].passwordEncoder.type=BCRYPT
|
cas.authn.jdbc.query[0].passwordEncoder.type=NONE
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
|
@ -1,16 +1,15 @@
|
||||||
cas.server.name: https://localhost:8443
|
cas.server.name: https://localhost:6443
|
||||||
cas.server.prefix: https://localhost:8443/cas
|
cas.server.prefix: https://localhost:643/cas
|
||||||
|
|
||||||
cas.adminPagesSecurity.ip=127\.0\.0\.1
|
cas.adminPagesSecurity.ip=127\.0\.0\.1
|
||||||
|
|
||||||
logging.config: file:/etc/cas/config/log4j2.xml
|
|
||||||
|
|
||||||
cas.serviceRegistry.initFromJson=true
|
cas.serviceRegistry.initFromJson=true
|
||||||
cas.serviceRegistry.config.location=classpath:/services
|
cas.serviceRegistry.config.location=classpath:/services
|
||||||
|
|
||||||
cas.authn.accept.users=
|
cas.authn.accept.users=
|
||||||
cas.authn.accept.name=
|
cas.authn.accept.name=
|
||||||
|
|
||||||
|
|
||||||
#CAS Database Authentication Property
|
#CAS Database Authentication Property
|
||||||
|
|
||||||
# cas.authn.jdbc.query[0].healthQuery=
|
# cas.authn.jdbc.query[0].healthQuery=
|
|
@ -0,0 +1,2 @@
|
||||||
|
info:
|
||||||
|
description: CAS Configuration
|
|
@ -0,0 +1,7 @@
|
||||||
|
cas.server.name: https://cas.example.org:8443
|
||||||
|
cas.server.prefix: https://cas.example.org:8443/cas
|
||||||
|
|
||||||
|
cas.adminPagesSecurity.ip=127\.0\.0\.1
|
||||||
|
|
||||||
|
logging.config: file:/etc/cas/config/log4j2.xml
|
||||||
|
# cas.serviceRegistry.config.location: classpath:/services
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!-- Specify the refresh internal in seconds. -->
|
||||||
|
<Configuration monitorInterval="5" packages="org.apereo.cas.logging">
|
||||||
|
<Properties>
|
||||||
|
<!--
|
||||||
|
Default log directory is the current directory but that can be overridden with -Dcas.log.dir=<logdir>
|
||||||
|
Or you can change this property to a new default
|
||||||
|
-->
|
||||||
|
<Property name="cas.log.dir" >.</Property>
|
||||||
|
<!-- To see more CAS specific logging, adjust this property to info or debug or run server with -Dcas.log.leve=debug -->
|
||||||
|
<Property name="cas.log.level" >warn</Property>
|
||||||
|
</Properties>
|
||||||
|
<Appenders>
|
||||||
|
<Console name="console" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout pattern="%d %p [%c] - <%m>%n"/>
|
||||||
|
</Console>
|
||||||
|
<RollingFile name="file" fileName="${sys:cas.log.dir}/cas.log" append="true"
|
||||||
|
filePattern="${sys:cas.log.dir}/cas-%d{yyyy-MM-dd-HH}-%i.log">
|
||||||
|
<PatternLayout pattern="%d %p [%c] - <%m>%n"/>
|
||||||
|
<Policies>
|
||||||
|
<OnStartupTriggeringPolicy />
|
||||||
|
<SizeBasedTriggeringPolicy size="10 MB"/>
|
||||||
|
<TimeBasedTriggeringPolicy />
|
||||||
|
</Policies>
|
||||||
|
</RollingFile>
|
||||||
|
<RollingFile name="auditlogfile" fileName="${sys:cas.log.dir}/cas_audit.log" append="true"
|
||||||
|
filePattern="${sys:cas.log.dir}/cas_audit-%d{yyyy-MM-dd-HH}-%i.log">
|
||||||
|
<PatternLayout pattern="%d %p [%c] - %m%n"/>
|
||||||
|
<Policies>
|
||||||
|
<OnStartupTriggeringPolicy />
|
||||||
|
<SizeBasedTriggeringPolicy size="10 MB"/>
|
||||||
|
<TimeBasedTriggeringPolicy />
|
||||||
|
</Policies>
|
||||||
|
</RollingFile>
|
||||||
|
|
||||||
|
<RollingFile name="perfFileAppender" fileName="${sys:cas.log.dir}/perfStats.log" append="true"
|
||||||
|
filePattern="${sys:cas.log.dir}/perfStats-%d{yyyy-MM-dd-HH}-%i.log">
|
||||||
|
<PatternLayout pattern="%m%n"/>
|
||||||
|
<Policies>
|
||||||
|
<OnStartupTriggeringPolicy />
|
||||||
|
<SizeBasedTriggeringPolicy size="10 MB"/>
|
||||||
|
<TimeBasedTriggeringPolicy />
|
||||||
|
</Policies>
|
||||||
|
</RollingFile>
|
||||||
|
|
||||||
|
<CasAppender name="casAudit">
|
||||||
|
<AppenderRef ref="auditlogfile" />
|
||||||
|
</CasAppender>
|
||||||
|
<CasAppender name="casFile">
|
||||||
|
<AppenderRef ref="file" />
|
||||||
|
</CasAppender>
|
||||||
|
<CasAppender name="casConsole">
|
||||||
|
<AppenderRef ref="console" />
|
||||||
|
</CasAppender>
|
||||||
|
<CasAppender name="casPerf">
|
||||||
|
<AppenderRef ref="perfFileAppender" />
|
||||||
|
</CasAppender>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<!-- If adding a Logger with level set higher than warn, make category as selective as possible -->
|
||||||
|
<!-- Loggers inherit appenders from Root Logger unless additivity is false -->
|
||||||
|
<AsyncLogger name="org.apereo" level="${sys:cas.log.level}" includeLocation="true"/>
|
||||||
|
<AsyncLogger name="org.apereo.services.persondir" level="${sys:cas.log.level}" includeLocation="true"/>
|
||||||
|
<AsyncLogger name="org.apereo.cas.web.flow" level="info" includeLocation="true"/>
|
||||||
|
<AsyncLogger name="org.apache" level="warn" />
|
||||||
|
<AsyncLogger name="org.apache.http" level="error" />
|
||||||
|
<AsyncLogger name="org.springframework" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.cloud.server" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.cloud.client" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.cloud.bus" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.aop" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.boot" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.boot.actuate.autoconfigure" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.webflow" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.session" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.amqp" level="error" />
|
||||||
|
<AsyncLogger name="org.springframework.integration" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.messaging" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.web" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.orm.jpa" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.scheduling" level="warn" />
|
||||||
|
<AsyncLogger name="org.springframework.context.annotation" level="error" />
|
||||||
|
<AsyncLogger name="org.springframework.boot.devtools" level="error" />
|
||||||
|
<AsyncLogger name="org.springframework.web.socket" level="warn" />
|
||||||
|
<AsyncLogger name="org.thymeleaf" level="warn" />
|
||||||
|
<AsyncLogger name="org.pac4j" level="warn" />
|
||||||
|
<AsyncLogger name="org.opensaml" level="warn"/>
|
||||||
|
<AsyncLogger name="net.sf.ehcache" level="warn" />
|
||||||
|
<AsyncLogger name="com.couchbase" level="warn" includeLocation="true"/>
|
||||||
|
<AsyncLogger name="com.ryantenney.metrics" level="warn" />
|
||||||
|
<AsyncLogger name="net.jradius" level="warn" />
|
||||||
|
<AsyncLogger name="org.openid4java" level="warn" />
|
||||||
|
<AsyncLogger name="org.ldaptive" level="warn" />
|
||||||
|
<AsyncLogger name="com.hazelcast" level="warn" />
|
||||||
|
<AsyncLogger name="org.jasig.spring" level="warn" />
|
||||||
|
|
||||||
|
<!-- Log perf stats only to perfStats.log -->
|
||||||
|
<AsyncLogger name="perfStatsLogger" level="info" additivity="false" includeLocation="true">
|
||||||
|
<AppenderRef ref="casPerf"/>
|
||||||
|
</AsyncLogger>
|
||||||
|
|
||||||
|
<!-- Log audit to all root appenders, and also to audit log (additivity is not false) -->
|
||||||
|
<AsyncLogger name="org.apereo.inspektr.audit.support" level="info" includeLocation="true" >
|
||||||
|
<AppenderRef ref="casAudit"/>
|
||||||
|
</AsyncLogger>
|
||||||
|
|
||||||
|
<!-- All Loggers inherit appenders specified here, unless additivity="false" on the Logger -->
|
||||||
|
<AsyncRoot level="warn">
|
||||||
|
<AppenderRef ref="casFile"/>
|
||||||
|
<!--
|
||||||
|
For deployment to an application server running as service,
|
||||||
|
delete the casConsole appender below
|
||||||
|
-->
|
||||||
|
<AppenderRef ref="casConsole"/>
|
||||||
|
</AsyncRoot>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.prime;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class PrimeGenerator {
|
||||||
|
public static List<Integer> sieveOfEratosthenes(int n) {
|
||||||
|
final boolean prime[] = new boolean[n + 1];
|
||||||
|
Arrays.fill(prime, true);
|
||||||
|
|
||||||
|
for (int p = 2; p * p <= n; p++) {
|
||||||
|
if (prime[p]) {
|
||||||
|
for (int i = p * 2; i <= n; i += p)
|
||||||
|
prime[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Integer> primes = new LinkedList<>();
|
||||||
|
for (int i = 2; i <= n; i++) {
|
||||||
|
if (prime[i])
|
||||||
|
primes.add(i);
|
||||||
|
}
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersBruteForce(int max) {
|
||||||
|
final List<Integer> primeNumbers = new LinkedList<Integer>();
|
||||||
|
for (int i = 2; i <= max; i++) {
|
||||||
|
if (isPrimeBruteForce(i)) {
|
||||||
|
primeNumbers.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primeNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrimeBruteForce(int x) {
|
||||||
|
for (int i = 2; i < x; i++) {
|
||||||
|
if (x % i == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersTill(int max) {
|
||||||
|
return IntStream.rangeClosed(2, max)
|
||||||
|
.filter(x -> isPrime(x))
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrime(int x) {
|
||||||
|
return IntStream.rangeClosed(2, (int) (Math.sqrt(x)))
|
||||||
|
.allMatch(n -> x % n != 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.prime;
|
||||||
|
|
||||||
|
import static com.baeldung.prime.PrimeGenerator.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PrimeGeneratorTest {
|
||||||
|
@Test
|
||||||
|
public void whenBruteForced_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersBruteForce(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOptimized_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersTill(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSieveOfEratosthenes_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = sieveOfEratosthenes(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,17 @@ package com.baeldung.concurrent.daemon;
|
||||||
public class NewThread extends Thread {
|
public class NewThread extends Thread {
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
while (true)
|
long startTime = System.currentTimeMillis();
|
||||||
for (int i = 0; i < 10; i++)
|
while (true) {
|
||||||
System.out.println("New Thread is running...");
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println("New Thread is running..." + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent the Thread to run forever. It will finish it's execution after 2 seconds
|
||||||
|
if (System.currentTimeMillis() - startTime > 2000) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.concurrent.executorservice;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
public class DelayedCallable implements Callable<String> {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private long period;
|
||||||
|
private CountDownLatch latch;
|
||||||
|
|
||||||
|
public DelayedCallable(String name, long period, CountDownLatch latch) {
|
||||||
|
this(name, period);
|
||||||
|
this.latch = latch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelayedCallable(String name, long period) {
|
||||||
|
this.name = name;
|
||||||
|
this.period = period;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String call() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(period);
|
||||||
|
|
||||||
|
if (latch != null) {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// handle exception
|
||||||
|
ex.printStackTrace();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,16 @@ package com.baeldung.concurrent.daemon;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
import org.junit.Ignore;
|
||||||
|
>>>>>>> d54917c7e9f0f74c40982571af8ac9f61782b7cb
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class DaemonThreadTest {
|
public class DaemonThreadTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
public void whenCallIsDaemon_thenCorrect() {
|
public void whenCallIsDaemon_thenCorrect() {
|
||||||
NewThread daemonThread = new NewThread();
|
NewThread daemonThread = new NewThread();
|
||||||
NewThread userThread = new NewThread();
|
NewThread userThread = new NewThread();
|
||||||
|
@ -20,6 +25,7 @@ public class DaemonThreadTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalThreadStateException.class)
|
@Test(expected = IllegalThreadStateException.class)
|
||||||
|
@Ignore
|
||||||
public void givenUserThread_whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
|
public void givenUserThread_whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
|
||||||
NewThread daemonThread = new NewThread();
|
NewThread daemonThread = new NewThread();
|
||||||
daemonThread.start();
|
daemonThread.start();
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
package com.baeldung.concurrent.executorservice;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
public class WaitingForThreadsToFinishTest {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishTest.class);
|
||||||
|
private final static ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
public void awaitTerminationAfterShutdown(ExecutorService threadPool) {
|
||||||
|
threadPool.shutdown();
|
||||||
|
try {
|
||||||
|
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||||
|
threadPool.shutdownNow();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
threadPool.shutdownNow();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenMultipleThreads_whenUsingCountDownLatch_thenMainShoudWaitForAllToFinish() {
|
||||||
|
|
||||||
|
ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// create a CountDownLatch that waits for the 2 threads to finish
|
||||||
|
CountDownLatch latch = new CountDownLatch(2);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
WORKER_THREAD_POOL.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
latch.countDown();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the latch to be decremented by the two threads
|
||||||
|
latch.await();
|
||||||
|
|
||||||
|
long processingTime = System.currentTimeMillis() - startTime;
|
||||||
|
assertTrue(processingTime >= 1000);
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenMultipleThreads_whenInvokeAll_thenMainThreadShouldWaitForAllToFinish() {
|
||||||
|
|
||||||
|
ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
|
||||||
|
|
||||||
|
List<Callable<String>> callables = Arrays.asList(
|
||||||
|
new DelayedCallable("fast thread", 100),
|
||||||
|
new DelayedCallable("slow thread", 3000));
|
||||||
|
|
||||||
|
try {
|
||||||
|
long startProcessingTime = System.currentTimeMillis();
|
||||||
|
List<Future<String>> futures = WORKER_THREAD_POOL.invokeAll(callables);
|
||||||
|
|
||||||
|
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
WORKER_THREAD_POOL.submit(new Callable<String>() {
|
||||||
|
@Override
|
||||||
|
public String call() throws Exception {
|
||||||
|
fail("This thread should have been rejected !");
|
||||||
|
Thread.sleep(1000000);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException ex) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
|
||||||
|
assertTrue(totalProcessingTime >= 3000);
|
||||||
|
|
||||||
|
String firstThreadResponse = futures.get(0)
|
||||||
|
.get();
|
||||||
|
assertTrue("First response should be from the fast thread", "fast thread".equals(firstThreadResponse));
|
||||||
|
|
||||||
|
String secondThreadResponse = futures.get(1)
|
||||||
|
.get();
|
||||||
|
assertTrue("Last response should be from the slow thread", "slow thread".equals(secondThreadResponse));
|
||||||
|
|
||||||
|
} catch (ExecutionException | InterruptedException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenMultipleThreads_whenUsingCompletionService_thenMainThreadShouldWaitForAllToFinish() {
|
||||||
|
|
||||||
|
CompletionService<String> service = new ExecutorCompletionService<>(WORKER_THREAD_POOL);
|
||||||
|
|
||||||
|
List<Callable<String>> callables = Arrays.asList(
|
||||||
|
new DelayedCallable("fast thread", 100),
|
||||||
|
new DelayedCallable("slow thread", 3000));
|
||||||
|
|
||||||
|
for (Callable<String> callable : callables) {
|
||||||
|
service.submit(callable);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
long startProcessingTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Future<String> future = service.take();
|
||||||
|
String firstThreadResponse = future.get();
|
||||||
|
long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
|
||||||
|
|
||||||
|
assertTrue("First response should be from the fast thread", "fast thread".equals(firstThreadResponse));
|
||||||
|
assertTrue(totalProcessingTime >= 100 && totalProcessingTime < 1000);
|
||||||
|
LOG.debug("Thread finished after: " + totalProcessingTime + " milliseconds");
|
||||||
|
|
||||||
|
future = service.take();
|
||||||
|
String secondThreadResponse = future.get();
|
||||||
|
totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
|
||||||
|
|
||||||
|
assertTrue("Last response should be from the slow thread", "slow thread".equals(secondThreadResponse));
|
||||||
|
assertTrue(totalProcessingTime >= 3000 && totalProcessingTime < 4000);
|
||||||
|
LOG.debug("Thread finished after: " + totalProcessingTime + " milliseconds");
|
||||||
|
|
||||||
|
} catch (ExecutionException | InterruptedException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenMultipleThreads_whenUsingCompletableFutures_thenMainThreadShouldWaitForAllToFinish() {
|
||||||
|
|
||||||
|
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Hello";
|
||||||
|
});
|
||||||
|
|
||||||
|
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Beautiful";
|
||||||
|
});
|
||||||
|
|
||||||
|
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(3000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "World";
|
||||||
|
});
|
||||||
|
|
||||||
|
long startProcessingTime = System.currentTimeMillis();
|
||||||
|
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2, future3);
|
||||||
|
combinedFuture.join();
|
||||||
|
|
||||||
|
long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
|
||||||
|
assertTrue(totalProcessingTime >= 5000 && totalProcessingTime < 6000);
|
||||||
|
|
||||||
|
LOG.debug("Responses from all threads are available after " + totalProcessingTime + " milliseconds");
|
||||||
|
|
||||||
|
try {
|
||||||
|
String thread1Response = future1.get();
|
||||||
|
assertTrue(thread1Response.equals("Hello"));
|
||||||
|
|
||||||
|
String thread2Response = future2.get();
|
||||||
|
assertTrue(thread2Response.equals("Beautiful"));
|
||||||
|
|
||||||
|
String thread3Response = future3.get();
|
||||||
|
assertTrue(thread3Response.equals("World"));
|
||||||
|
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +1,50 @@
|
||||||
package com.baeldung.concurrent.runnable;
|
package com.baeldung.concurrent.runnable;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.junit.After;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class RunnableVsThreadTest {
|
public class RunnableVsThreadLiveTest {
|
||||||
|
|
||||||
private static Logger log =
|
private static Logger log =
|
||||||
LoggerFactory.getLogger(RunnableVsThreadTest.class);
|
LoggerFactory.getLogger(RunnableVsThreadLiveTest.class);
|
||||||
|
|
||||||
|
private static ExecutorService executorService;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setup() {
|
||||||
|
executorService = Executors.newCachedThreadPool();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenARunnable_whenRunIt_thenResult() throws Exception{
|
public void givenARunnable_whenRunIt_thenResult() throws Exception{
|
||||||
Thread thread = new Thread(new SimpleRunnable(
|
Thread thread = new Thread(new SimpleRunnable(
|
||||||
"SimpleRunnable executed using Thread"));
|
"SimpleRunnable executed using Thread"));
|
||||||
thread.start();
|
thread.start();
|
||||||
thread.join();
|
thread.join();
|
||||||
|
}
|
||||||
ExecutorService executorService =
|
|
||||||
Executors.newCachedThreadPool();
|
@Test
|
||||||
|
public void givenARunnable_whenSubmitToES_thenResult() throws Exception{
|
||||||
|
|
||||||
executorService.submit(new SimpleRunnable(
|
executorService.submit(new SimpleRunnable(
|
||||||
"SimpleRunnable executed using ExecutorService")).get();
|
"SimpleRunnable executed using ExecutorService")).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenARunnableLambda_whenSubmitToES_thenResult()
|
||||||
|
throws Exception{
|
||||||
|
|
||||||
executorService.submit(()->
|
executorService.submit(()->
|
||||||
log.info("Lambda runnable executed!!!")).get();
|
log.info("Lambda runnable executed!!!")).get();
|
||||||
executorService.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -42,26 +53,37 @@ public class RunnableVsThreadTest {
|
||||||
"SimpleThread executed using Thread");
|
"SimpleThread executed using Thread");
|
||||||
thread.start();
|
thread.start();
|
||||||
thread.join();
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAThread_whenSubmitToES_thenResult() throws Exception{
|
||||||
|
|
||||||
ExecutorService executorService =
|
|
||||||
Executors.newCachedThreadPool();
|
|
||||||
executorService.submit(new SimpleThread(
|
executorService.submit(new SimpleThread(
|
||||||
"SimpleThread executed using ExecutorService")).get();
|
"SimpleThread executed using ExecutorService")).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenACallable_whenRunIt_thenResult() throws Exception {
|
public void givenACallable_whenSubmitToES_thenResult() throws Exception {
|
||||||
ExecutorService executorService =
|
|
||||||
Executors.newCachedThreadPool();
|
|
||||||
|
|
||||||
Future<Integer> future = executorService.submit(new SimpleCallable());
|
Future<Integer> future = executorService.submit(
|
||||||
|
new SimpleCallable());
|
||||||
log.info("Result from callable: {}", future.get());
|
log.info("Result from callable: {}", future.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenACallableAsLambda_whenSubmitToES_thenResult()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
Future<Integer> future = executorService.submit(() -> RandomUtils.nextInt(0, 100));
|
||||||
|
|
||||||
future = executorService.submit(() -> {
|
|
||||||
return RandomUtils.nextInt(0, 100);
|
|
||||||
});
|
|
||||||
log.info("Result from callable: {}", future.get());
|
log.info("Result from callable: {}", future.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDown() {
|
||||||
|
if ( executorService != null && !executorService.isShutdown()) {
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +94,7 @@ class SimpleThread extends Thread{
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public SimpleThread(String message) {
|
SimpleThread(String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +111,7 @@ class SimpleRunnable implements Runnable {
|
||||||
|
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public SimpleRunnable(String message) {
|
SimpleRunnable(String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,4 +129,5 @@ class SimpleCallable implements Callable<Integer> {
|
||||||
return RandomUtils.nextInt(0, 100);
|
return RandomUtils.nextInt(0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,4 +114,5 @@
|
||||||
- [StringBuilder and StringBuffer in Java](http://www.baeldung.com/java-string-builder-string-buffer)
|
- [StringBuilder and StringBuffer in Java](http://www.baeldung.com/java-string-builder-string-buffer)
|
||||||
- [Number of Digits in an Integer in Java](http://www.baeldung.com/java-number-of-digits-in-int)
|
- [Number of Digits in an Integer in Java](http://www.baeldung.com/java-number-of-digits-in-int)
|
||||||
- [Proxy, Decorator, Adapter and Bridge Patterns](http://www.baeldung.com/java-structural-design-patterns)
|
- [Proxy, Decorator, Adapter and Bridge Patterns](http://www.baeldung.com/java-structural-design-patterns)
|
||||||
|
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,13 @@
|
||||||
<artifactId>spring-web</artifactId>
|
<artifactId>spring-web</artifactId>
|
||||||
<version>4.3.4.RELEASE</version>
|
<version>4.3.4.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun</groupId>
|
||||||
|
<artifactId>tools</artifactId>
|
||||||
|
<version>1.8.0</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${java.home}/../lib/tools.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -249,7 +256,7 @@
|
||||||
<exclude>**/*LongRunningUnitTest.java</exclude>
|
<exclude>**/*LongRunningUnitTest.java</exclude>
|
||||||
<exclude>**/*ManualTest.java</exclude>
|
<exclude>**/*ManualTest.java</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
<testFailureIgnore>true</testFailureIgnore>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
package com.baeldung.breakcontinue;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Santosh
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BreakContinue {
|
||||||
|
|
||||||
|
public static int unlabeledBreak() {
|
||||||
|
String searchName = "Wilson";
|
||||||
|
int counter = 0;
|
||||||
|
List<String> names = Arrays.asList("John", "Peter", "Robert", "Wilson", "Anthony", "Donald", "Richard");
|
||||||
|
|
||||||
|
for (String name : names) {
|
||||||
|
counter++;
|
||||||
|
if (name.equalsIgnoreCase(searchName)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unlabeledBreakNestedLoops() {
|
||||||
|
String searchName = "Wilson";
|
||||||
|
int counter = 0;
|
||||||
|
Map<String, List<String>> nameMap = new HashMap<>();
|
||||||
|
nameMap.put("Grade1", Arrays.asList("John", "Peter", "Robert", "Wilson"));
|
||||||
|
nameMap.put("Grade2", Arrays.asList("Anthony", "Donald", "Richard", "Arnold"));
|
||||||
|
nameMap.put("Grade3", Arrays.asList("Wilson", "Michael", "Stephen", "Ryan"));
|
||||||
|
|
||||||
|
Iterator<Entry<String, List<String>>> iterator = nameMap.entrySet()
|
||||||
|
.iterator();
|
||||||
|
Entry<String, List<String>> entry = null;
|
||||||
|
List<String> names = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
entry = iterator.next();
|
||||||
|
names = entry.getValue();
|
||||||
|
for (String name : names) {
|
||||||
|
if (name.equalsIgnoreCase(searchName)) {
|
||||||
|
counter++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int labeledBreak() {
|
||||||
|
String searchName = "Wilson";
|
||||||
|
int counter = 0;
|
||||||
|
Map<String, List<String>> nameMap = new HashMap<>();
|
||||||
|
nameMap.put("Grade1", Arrays.asList("John", "Peter", "Robert", "Wilson"));
|
||||||
|
nameMap.put("Grade2", Arrays.asList("Anthony", "Donald", "Richard", "Arnold"));
|
||||||
|
nameMap.put("Grade3", Arrays.asList("Wilson", "Michael", "Stephen", "Ryan"));
|
||||||
|
|
||||||
|
Iterator<Entry<String, List<String>>> iterator = nameMap.entrySet()
|
||||||
|
.iterator();
|
||||||
|
Entry<String, List<String>> entry = null;
|
||||||
|
List<String> names = null;
|
||||||
|
compare:
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
entry = iterator.next();
|
||||||
|
names = entry.getValue();
|
||||||
|
for (String name : names) {
|
||||||
|
if (name.equalsIgnoreCase(searchName)) {
|
||||||
|
counter++;
|
||||||
|
break compare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unlabeledContinue() {
|
||||||
|
String searchName = "Wilson";
|
||||||
|
int counter = 0;
|
||||||
|
Map<String, List<String>> nameMap = new HashMap<>();
|
||||||
|
nameMap.put("Grade1", Arrays.asList("John", "Wilson", "Robert", "Wilson"));
|
||||||
|
nameMap.put("Grade2", Arrays.asList("Anthony", "Donald", "Wilson", "Arnold"));
|
||||||
|
nameMap.put("Grade3", Arrays.asList("Wilson", "Michael", "Wilson", "Ryan"));
|
||||||
|
|
||||||
|
Iterator<Entry<String, List<String>>> iterator = nameMap.entrySet()
|
||||||
|
.iterator();
|
||||||
|
Entry<String, List<String>> entry = null;
|
||||||
|
List<String> names = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
entry = iterator.next();
|
||||||
|
names = entry.getValue();
|
||||||
|
for (String name : names) {
|
||||||
|
if (!name.equalsIgnoreCase(searchName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int labeledContinue() {
|
||||||
|
String searchName = "Wilson";
|
||||||
|
int counter = 0;
|
||||||
|
Map<String, List<String>> nameMap = new HashMap<>();
|
||||||
|
nameMap.put("Grade1", Arrays.asList("John", "Wilson", "Robert", "Wilson"));
|
||||||
|
nameMap.put("Grade2", Arrays.asList("Anthony", "Donald", "Wilson", "Arnold"));
|
||||||
|
nameMap.put("Grade3", Arrays.asList("Wilson", "Michael", "Wilson", "Ryan"));
|
||||||
|
|
||||||
|
Iterator<Entry<String, List<String>>> iterator = nameMap.entrySet()
|
||||||
|
.iterator();
|
||||||
|
Entry<String, List<String>> entry = null;
|
||||||
|
List<String> names = null;
|
||||||
|
compare:
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
entry = iterator.next();
|
||||||
|
names = entry.getValue();
|
||||||
|
for (String name : names) {
|
||||||
|
if (name.equalsIgnoreCase(searchName)) {
|
||||||
|
counter++;
|
||||||
|
continue compare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,6 +13,8 @@ import java.util.Set;
|
||||||
|
|
||||||
public class EchoServer {
|
public class EchoServer {
|
||||||
|
|
||||||
|
private static final String POISON_PILL = "POISON_PILL";
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
Selector selector = Selector.open();
|
Selector selector = Selector.open();
|
||||||
ServerSocketChannel serverSocket = ServerSocketChannel.open();
|
ServerSocketChannel serverSocket = ServerSocketChannel.open();
|
||||||
|
@ -30,23 +32,36 @@ public class EchoServer {
|
||||||
SelectionKey key = iter.next();
|
SelectionKey key = iter.next();
|
||||||
|
|
||||||
if (key.isAcceptable()) {
|
if (key.isAcceptable()) {
|
||||||
SocketChannel client = serverSocket.accept();
|
register(selector, serverSocket);
|
||||||
client.configureBlocking(false);
|
|
||||||
client.register(selector, SelectionKey.OP_READ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.isReadable()) {
|
if (key.isReadable()) {
|
||||||
SocketChannel client = (SocketChannel) key.channel();
|
answerWithEcho(buffer, key);
|
||||||
client.read(buffer);
|
|
||||||
buffer.flip();
|
|
||||||
client.write(buffer);
|
|
||||||
buffer.clear();
|
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void answerWithEcho(ByteBuffer buffer, SelectionKey key) throws IOException {
|
||||||
|
SocketChannel client = (SocketChannel) key.channel();
|
||||||
|
client.read(buffer);
|
||||||
|
if (new String(buffer.array()).trim().equals(POISON_PILL)) {
|
||||||
|
client.close();
|
||||||
|
System.out.println("Not accepting client messages anymore");
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.flip();
|
||||||
|
client.write(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void register(Selector selector, ServerSocketChannel serverSocket) throws IOException {
|
||||||
|
SocketChannel client = serverSocket.accept();
|
||||||
|
client.configureBlocking(false);
|
||||||
|
client.register(selector, SelectionKey.OP_READ);
|
||||||
|
}
|
||||||
|
|
||||||
public static Process start() throws IOException, InterruptedException {
|
public static Process start() throws IOException, InterruptedException {
|
||||||
String javaHome = System.getProperty("java.home");
|
String javaHome = System.getProperty("java.home");
|
||||||
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
|
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
public @interface Positive {
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import com.sun.source.tree.MethodTree;
|
||||||
|
import com.sun.source.tree.VariableTree;
|
||||||
|
import com.sun.source.util.*;
|
||||||
|
import com.sun.tools.javac.api.BasicJavacTask;
|
||||||
|
import com.sun.tools.javac.code.TypeTag;
|
||||||
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
|
import com.sun.tools.javac.tree.TreeMaker;
|
||||||
|
import com.sun.tools.javac.util.Context;
|
||||||
|
import com.sun.tools.javac.util.Name;
|
||||||
|
import com.sun.tools.javac.util.Names;
|
||||||
|
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.sun.tools.javac.util.List.nil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link JavaCompiler javac} plugin which inserts {@code >= 0} checks into resulting {@code *.class} files
|
||||||
|
* for numeric method parameters marked by {@link Positive}
|
||||||
|
*/
|
||||||
|
public class SampleJavacPlugin implements Plugin {
|
||||||
|
|
||||||
|
public static final String NAME = "MyPlugin";
|
||||||
|
|
||||||
|
private static Set<String> TARGET_TYPES = new HashSet<>(Arrays.asList(
|
||||||
|
// Use only primitive types for simplicity
|
||||||
|
byte.class.getName(), short.class.getName(), char.class.getName(),
|
||||||
|
int.class.getName(), long.class.getName(), float.class.getName(), double.class.getName()));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(JavacTask task, String... args) {
|
||||||
|
Context context = ((BasicJavacTask) task).getContext();
|
||||||
|
task.addTaskListener(new TaskListener() {
|
||||||
|
@Override
|
||||||
|
public void started(TaskEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finished(TaskEvent e) {
|
||||||
|
if (e.getKind() != TaskEvent.Kind.PARSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.getCompilationUnit()
|
||||||
|
.accept(new TreeScanner<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitMethod(MethodTree method, Void v) {
|
||||||
|
List<VariableTree> parametersToInstrument = method.getParameters()
|
||||||
|
.stream()
|
||||||
|
.filter(SampleJavacPlugin.this::shouldInstrument)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!parametersToInstrument.isEmpty()) {
|
||||||
|
// There is a possible case that more than one argument is marked by @Positive,
|
||||||
|
// as the checks are added to the method's body beginning, we process parameters RTL
|
||||||
|
// to ensure correct order.
|
||||||
|
Collections.reverse(parametersToInstrument);
|
||||||
|
parametersToInstrument.forEach(p -> addCheck(method, p, context));
|
||||||
|
}
|
||||||
|
// There is a possible case that there is a nested class declared in a method's body,
|
||||||
|
// hence, we want to proceed with method body AST as well.
|
||||||
|
return super.visitMethod(method, v);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldInstrument(VariableTree parameter) {
|
||||||
|
return TARGET_TYPES.contains(parameter.getType().toString())
|
||||||
|
&& parameter.getModifiers().getAnnotations()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(a -> Positive.class.getSimpleName().equals(a.getAnnotationType().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCheck(MethodTree method, VariableTree parameter, Context context) {
|
||||||
|
JCTree.JCIf check = createCheck(parameter, context);
|
||||||
|
JCTree.JCBlock body = (JCTree.JCBlock) method.getBody();
|
||||||
|
body.stats = body.stats.prepend(check);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JCTree.JCIf createCheck(VariableTree parameter, Context context) {
|
||||||
|
TreeMaker factory = TreeMaker.instance(context);
|
||||||
|
Names symbolsTable = Names.instance(context);
|
||||||
|
|
||||||
|
return factory.at(((JCTree) parameter).pos)
|
||||||
|
.If(factory.Parens(createIfCondition(factory, symbolsTable, parameter)),
|
||||||
|
createIfBlock(factory, symbolsTable, parameter),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JCTree.JCBinary createIfCondition(TreeMaker factory, Names symbolsTable, VariableTree parameter) {
|
||||||
|
Name parameterId = symbolsTable.fromString(parameter.getName().toString());
|
||||||
|
return factory.Binary(JCTree.Tag.LE,
|
||||||
|
factory.Ident(parameterId),
|
||||||
|
factory.Literal(TypeTag.INT, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JCTree.JCBlock createIfBlock(TreeMaker factory, Names symbolsTable, VariableTree parameter) {
|
||||||
|
String parameterName = parameter.getName().toString();
|
||||||
|
Name parameterId = symbolsTable.fromString(parameterName);
|
||||||
|
|
||||||
|
String errorMessagePrefix = String.format("Argument '%s' of type %s is marked by @%s but got '",
|
||||||
|
parameterName, parameter.getType(), Positive.class.getSimpleName());
|
||||||
|
String errorMessageSuffix = "' for it";
|
||||||
|
|
||||||
|
return factory.Block(0, com.sun.tools.javac.util.List.of(
|
||||||
|
factory.Throw(
|
||||||
|
factory.NewClass(null, nil(),
|
||||||
|
factory.Ident(symbolsTable.fromString(IllegalArgumentException.class.getSimpleName())),
|
||||||
|
com.sun.tools.javac.util.List.of(factory.Binary(JCTree.Tag.PLUS,
|
||||||
|
factory.Binary(JCTree.Tag.PLUS, factory.Literal(TypeTag.CLASS, errorMessagePrefix),
|
||||||
|
factory.Ident(parameterId)),
|
||||||
|
factory.Literal(TypeTag.CLASS, errorMessageSuffix))), null))));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
com.baeldung.javac.SampleJavacPlugin
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.breakcontinue;
|
||||||
|
|
||||||
|
import static com.baeldung.breakcontinue.BreakContinue.labeledBreak;
|
||||||
|
import static com.baeldung.breakcontinue.BreakContinue.labeledContinue;
|
||||||
|
import static com.baeldung.breakcontinue.BreakContinue.unlabeledBreak;
|
||||||
|
import static com.baeldung.breakcontinue.BreakContinue.unlabeledBreakNestedLoops;
|
||||||
|
import static com.baeldung.breakcontinue.BreakContinue.unlabeledContinue;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class BreakContinueTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUnlabeledBreak_ThenEqual() {
|
||||||
|
assertEquals(4, unlabeledBreak());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUnlabeledBreakNestedLoops_ThenEqual() {
|
||||||
|
assertEquals(2, unlabeledBreakNestedLoops());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLabeledBreak_ThenEqual() {
|
||||||
|
assertEquals(1, labeledBreak());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUnlabeledContinue_ThenEqual() {
|
||||||
|
assertEquals(5, unlabeledContinue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLabeledContinue_ThenEqual() {
|
||||||
|
assertEquals(3, labeledContinue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class SampleJavacPluginIntegrationTest {
|
||||||
|
|
||||||
|
private static final String CLASS_TEMPLATE =
|
||||||
|
"package com.baeldung.javac;\n" +
|
||||||
|
"\n" +
|
||||||
|
"public class Test {\n" +
|
||||||
|
" public static %1$s service(@Positive %1$s i) {\n" +
|
||||||
|
" return i;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}\n" +
|
||||||
|
"";
|
||||||
|
|
||||||
|
private TestCompiler compiler = new TestCompiler();
|
||||||
|
private TestRunner runner = new TestRunner();
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void givenInt_whenNegative_thenThrowsException() throws Throwable {
|
||||||
|
compileAndRun(double.class,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void givenInt_whenZero_thenThrowsException() throws Throwable {
|
||||||
|
compileAndRun(int.class,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInt_whenPositive_thenSuccess() throws Throwable {
|
||||||
|
assertEquals(1, compileAndRun(int.class, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object compileAndRun(Class<?> argumentType, Object argument) throws Throwable {
|
||||||
|
String qualifiedClassName = "com.baeldung.javac.Test";
|
||||||
|
byte[] byteCode = compiler.compile(qualifiedClassName, String.format(CLASS_TEMPLATE, argumentType.getName()));
|
||||||
|
return runner.run(byteCode, qualifiedClassName, "service", new Class[] {argumentType}, argument);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/** Holds compiled byte code in a byte array */
|
||||||
|
public class SimpleClassFile extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
private ByteArrayOutputStream out;
|
||||||
|
|
||||||
|
public SimpleClassFile(URI uri) {
|
||||||
|
super(uri, Kind.CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputStream openOutputStream() throws IOException {
|
||||||
|
return out = new ByteArrayOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getCompiledBinaries() {
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import javax.tools.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Adapts {@link SimpleClassFile} to the {@link JavaCompiler} */
|
||||||
|
public class SimpleFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
|
||||||
|
|
||||||
|
private final List<SimpleClassFile> compiled = new ArrayList<>();
|
||||||
|
|
||||||
|
public SimpleFileManager(StandardJavaFileManager delegate) {
|
||||||
|
super(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaFileObject getJavaFileForOutput(Location location,
|
||||||
|
String className,
|
||||||
|
JavaFileObject.Kind kind,
|
||||||
|
FileObject sibling)
|
||||||
|
{
|
||||||
|
SimpleClassFile result = new SimpleClassFile(URI.create("string://" + className));
|
||||||
|
compiled.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return compiled binaries processed by the current class
|
||||||
|
*/
|
||||||
|
public List<SimpleClassFile> getCompiled() {
|
||||||
|
return compiled;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import javax.tools.SimpleJavaFileObject;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/** Exposes given test source to the compiler. */
|
||||||
|
public class SimpleSourceFile extends SimpleJavaFileObject {
|
||||||
|
|
||||||
|
private final String content;
|
||||||
|
|
||||||
|
public SimpleSourceFile(String qualifiedClassName, String testSource) {
|
||||||
|
super(URI.create(String.format("file://%s%s",
|
||||||
|
qualifiedClassName.replaceAll("\\.", "/"),
|
||||||
|
Kind.SOURCE.extension)),
|
||||||
|
Kind.SOURCE);
|
||||||
|
content = testSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
|
||||||
|
public class TestCompiler {
|
||||||
|
public byte[] compile(String qualifiedClassName, String testSource) {
|
||||||
|
StringWriter output = new StringWriter();
|
||||||
|
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
SimpleFileManager fileManager = new SimpleFileManager(compiler.getStandardFileManager(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
));
|
||||||
|
List<SimpleSourceFile> compilationUnits = singletonList(new SimpleSourceFile(qualifiedClassName, testSource));
|
||||||
|
List<String> arguments = new ArrayList<>();
|
||||||
|
arguments.addAll(asList("-classpath", System.getProperty("java.class.path"),
|
||||||
|
"-Xplugin:" + SampleJavacPlugin.NAME));
|
||||||
|
JavaCompiler.CompilationTask task = compiler.getTask(output,
|
||||||
|
fileManager,
|
||||||
|
null,
|
||||||
|
arguments,
|
||||||
|
null,
|
||||||
|
compilationUnits);
|
||||||
|
task.call();
|
||||||
|
return fileManager.getCompiled().iterator().next().getCompiledBinaries();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.javac;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class TestRunner {
|
||||||
|
|
||||||
|
public Object run(byte[] byteCode,
|
||||||
|
String qualifiedClassName,
|
||||||
|
String methodName,
|
||||||
|
Class<?>[] argumentTypes,
|
||||||
|
Object... args)
|
||||||
|
throws Throwable
|
||||||
|
{
|
||||||
|
ClassLoader classLoader = new ClassLoader() {
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
return defineClass(name, byteCode, 0, byteCode.length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Class<?> clazz;
|
||||||
|
try {
|
||||||
|
clazz = classLoader.loadClass(qualifiedClassName);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("Can't load compiled test class", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Method method;
|
||||||
|
try {
|
||||||
|
method = clazz.getMethod(methodName, argumentTypes);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("Can't find the 'main()' method in the compiled test class", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return method.invoke(null, args);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
package com.baeldung.stack;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
public class StackUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStackIsCreated_thenItHasSize0() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
assertEquals(0, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStack_whenElementIsPushed_thenStackSizeisIncreased() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
intStack.push(1);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStack_whenMultipleElementsArePushed_thenStackSizeisIncreased() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
boolean result = intStack.addAll(intList);
|
||||||
|
assertTrue(result);
|
||||||
|
assertEquals(7, intList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.pop();
|
||||||
|
assertTrue(intStack.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.peek();
|
||||||
|
assertEquals(1, intStack.search(5));
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsOnStack_thenSearchReturnsItsDistanceFromTheTop() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
assertEquals(1, intStack.search(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsOnStack_thenIndexOfReturnsItsIndex() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
int indexOf = intStack.indexOf(5);
|
||||||
|
assertEquals(0, indexOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenMultipleElementsAreOnStack_thenIndexOfReturnsLastElementIndex() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
int lastIndexOf = intStack.lastIndexOf(5);
|
||||||
|
assertEquals(2, lastIndexOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementOnStack_whenRemoveElementIsInvoked_thenElementIsRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.removeElement(5);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementOnStack_whenRemoveElementAtIsInvoked_thenElementIsRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(7);
|
||||||
|
intStack.removeElementAt(1);
|
||||||
|
assertEquals(-1, intStack.search(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveAllElementsIsInvoked_thenAllElementsAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(7);
|
||||||
|
intStack.removeAllElements();
|
||||||
|
assertTrue(intStack.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveAllIsInvoked_thenAllElementsFromCollectionAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
intStack.add(500);
|
||||||
|
intStack.removeAll(intList);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveIfIsInvoked_thenAllElementsSatysfyingConditionAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
intStack.removeIf(element -> element < 6);
|
||||||
|
assertEquals(2, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAnotherStackCreatedWhileTraversingStack_thenStacksAreEqual() {
|
||||||
|
Stack<Integer> intStack = new Stack<>();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
ListIterator<Integer> it = intStack.listIterator();
|
||||||
|
Stack<Integer> result = new Stack();
|
||||||
|
while(it.hasNext()) {
|
||||||
|
result.push(it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(result, equalTo(intStack));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
package com.baeldung.string.formatter;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Formatter;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class StringFormatterExampleTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenFormatSpecifierForCalendar_thenGotExpected() {
|
||||||
|
//Syntax of Format Specifiers for Date/Time Representation
|
||||||
|
Calendar c = new GregorianCalendar(2017, 11, 10);
|
||||||
|
String s = String.format("The date is: %1$tm %1$te,%1$tY", c);
|
||||||
|
|
||||||
|
assertEquals("The date is: 12 10,2017", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenGeneralConversion_thenConvertedString() {
|
||||||
|
//General Conversions
|
||||||
|
String s = String.format("The correct answer is %s", false);
|
||||||
|
assertEquals("The correct answer is false", s);
|
||||||
|
|
||||||
|
s = String.format("The correct answer is %b", null);
|
||||||
|
assertEquals("The correct answer is false", s);
|
||||||
|
|
||||||
|
s = String.format("The correct answer is %B", true);
|
||||||
|
assertEquals("The correct answer is TRUE", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenCharConversion_thenConvertedString() {
|
||||||
|
//Character Conversions
|
||||||
|
String s = String.format("The correct answer is %c", 'a');
|
||||||
|
assertEquals("The correct answer is a", s);
|
||||||
|
|
||||||
|
s = String.format("The correct answer is %c", null);
|
||||||
|
assertEquals("The correct answer is null", s);
|
||||||
|
|
||||||
|
s = String.format("The correct answer is %C", 'b');
|
||||||
|
assertEquals("The correct answer is B", s);
|
||||||
|
|
||||||
|
s = String.format("The valid unicode character: %c", 0x0400);
|
||||||
|
assertTrue(Character.isValidCodePoint(0x0400));
|
||||||
|
assertEquals("The valid unicode character: Ѐ", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = java.util.IllegalFormatCodePointException.class)
|
||||||
|
public void givenString_whenIllegalCodePointForConversion_thenError() {
|
||||||
|
String s = String.format("The valid unicode character: %c", 0x11FFFF);
|
||||||
|
assertFalse(Character.isValidCodePoint(0x11FFFF));
|
||||||
|
assertEquals("The valid unicode character: Ā", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenNumericIntegralConversion_thenConvertedString() {
|
||||||
|
//Numeric Integral Conversions
|
||||||
|
String s = String.format("The number 25 in decimal = %d", 25);
|
||||||
|
assertEquals("The number 25 in decimal = 25", s);
|
||||||
|
|
||||||
|
s = String.format("The number 25 in octal = %o", 25);
|
||||||
|
assertEquals("The number 25 in octal = 31", s);
|
||||||
|
|
||||||
|
s = String.format("The number 25 in hexadecimal = %x", 25);
|
||||||
|
assertEquals("The number 25 in hexadecimal = 19", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenNumericFloatingConversion_thenConvertedString() {
|
||||||
|
//Numeric Floating-point Conversions
|
||||||
|
String s = String.format("The computerized scientific format of 10000.00 "
|
||||||
|
+ "= %e", 10000.00);
|
||||||
|
assertEquals("The computerized scientific format of 10000.00 = 1.000000e+04", s);
|
||||||
|
|
||||||
|
s = String.format("The decimal format of 10.019 = %f", 10.019);
|
||||||
|
assertEquals("The decimal format of 10.019 = 10.019000", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenLineSeparatorConversion_thenConvertedString() {
|
||||||
|
//Line Separator Conversion
|
||||||
|
String s = String.format("First Line %nSecond Line");
|
||||||
|
assertEquals("First Line \n"
|
||||||
|
+ "Second Line", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenSpecifyFlag_thenGotFormattedString() {
|
||||||
|
//Without left-justified flag
|
||||||
|
String s = String.format("Without left justified flag: %5d", 25);
|
||||||
|
assertEquals("Without left justified flag: 25", s);
|
||||||
|
|
||||||
|
//Using left-justified flag
|
||||||
|
s = String.format("With left justified flag: %-5d", 25);
|
||||||
|
assertEquals("With left justified flag: 25 ", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenSpecifyPrecision_thenGotExpected() {
|
||||||
|
|
||||||
|
//Precision
|
||||||
|
String s = String.format("Output of 25.09878 with Precision 2: %.2f", 25.09878);
|
||||||
|
assertEquals("Output of 25.09878 with Precision 2: 25.10", s);
|
||||||
|
|
||||||
|
s = String.format("Output of general conversion type with Precision 2: %.2b", true);
|
||||||
|
assertEquals("Output of general conversion type with Precision 2: tr", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenSpecifyArgumentIndex_thenGotExpected() {
|
||||||
|
Calendar c = new GregorianCalendar(2017, 11, 10);
|
||||||
|
//Argument_Index
|
||||||
|
String s = String.format("The date is: %1$tm %1$te,%1$tY", c);
|
||||||
|
assertEquals("The date is: 12 10,2017", s);
|
||||||
|
|
||||||
|
s = String.format("The date is: %1$tm %<te,%<tY", c);
|
||||||
|
assertEquals("The date is: 12 10,2017", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAppendable_whenCreateFormatter_thenFormatterWorksOnAppendable() {
|
||||||
|
//Using String Formatter with Appendable
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Formatter formatter = new Formatter(sb);
|
||||||
|
formatter.format("I am writting to a %1$s Instance.", sb.getClass());
|
||||||
|
|
||||||
|
assertEquals("I am writting to a class java.lang.StringBuilder Instance.", sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenString_whenNoArguments_thenExpected() {
|
||||||
|
//Using String Formatter without arguments
|
||||||
|
String s = String.format("John scored 90%% in Fall semester");
|
||||||
|
assertEquals("John scored 90% in Fall semester", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.stringpool;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
|
||||||
|
public class StringPoolUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingConstantStrings_thenTheirAddressesAreEqual() {
|
||||||
|
String constantString1 = "Baeldung";
|
||||||
|
String constantString2 = "Baeldung";
|
||||||
|
|
||||||
|
assertThat(constantString1).isSameAs(constantString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingStringsWithTheNewOperator_thenTheirAddressesAreDifferent() {
|
||||||
|
String newString1 = new String("Baeldung");
|
||||||
|
String newString2 = new String("Baeldung");
|
||||||
|
|
||||||
|
assertThat(newString1).isNotSameAs(newString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenComparingConstantAndNewStrings_thenTheirAddressesAreDifferent() {
|
||||||
|
String constantString = "Baeldung";
|
||||||
|
String newString = new String("Baeldung");
|
||||||
|
|
||||||
|
assertThat(constantString).isNotSameAs(newString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInterningAStringWithIdenticalValueToAnother_thenTheirAddressesAreEqual() {
|
||||||
|
String constantString = "interned Baeldung";
|
||||||
|
String newString = new String("interned Baeldung");
|
||||||
|
|
||||||
|
assertThat(constantString).isNotSameAs(newString);
|
||||||
|
|
||||||
|
String internedString = newString.intern();
|
||||||
|
|
||||||
|
assertThat(constantString).isSameAs(internedString);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,5 +15,6 @@
|
||||||
- [Data Classes in Kotlin](http://www.baeldung.com/kotlin-data-classes)
|
- [Data Classes in Kotlin](http://www.baeldung.com/kotlin-data-classes)
|
||||||
- [Delegated Properties in Kotlin](http://www.baeldung.com/kotlin-delegated-properties)
|
- [Delegated Properties in Kotlin](http://www.baeldung.com/kotlin-delegated-properties)
|
||||||
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
|
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
|
||||||
|
- [JUnit 5 for Kotlin Developers](http://www.baeldung.com/junit-5-kotlin)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
class UseDuration {
|
||||||
|
|
||||||
|
fun modifyDates(localTime: LocalTime, duration: Duration): LocalTime {
|
||||||
|
return localTime.plus(duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDifferenceBetweenDates(localTime1: LocalTime, localTime2: LocalTime): Duration {
|
||||||
|
return Duration.between(localTime1, localTime2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.DayOfWeek
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
import java.time.temporal.TemporalAdjusters
|
||||||
|
|
||||||
|
class UseLocalDate {
|
||||||
|
|
||||||
|
fun getLocalDateUsingFactoryOfMethod(year: Int, month: Int, dayOfMonth: Int): LocalDate {
|
||||||
|
return LocalDate.of(year, month, dayOfMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalDateUsingParseMethod(representation: String): LocalDate {
|
||||||
|
return LocalDate.parse(representation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalDateFromClock(): LocalDate {
|
||||||
|
return LocalDate.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextDay(localDate: LocalDate): LocalDate {
|
||||||
|
return localDate.plusDays(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPreviousDay(localDate: LocalDate): LocalDate {
|
||||||
|
return localDate.minus(1, ChronoUnit.DAYS)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDayOfWeek(localDate: LocalDate): DayOfWeek {
|
||||||
|
return localDate.dayOfWeek
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFirstDayOfMonth(): LocalDate {
|
||||||
|
return LocalDate.now().with(TemporalAdjusters.firstDayOfMonth())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getStartOfDay(localDate: LocalDate): LocalDateTime {
|
||||||
|
return localDate.atStartOfDay()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
class UseLocalDateTime {
|
||||||
|
|
||||||
|
fun getLocalDateTimeUsingParseMethod(representation: String): LocalDateTime {
|
||||||
|
return LocalDateTime.parse(representation)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.LocalTime
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
|
class UseLocalTime {
|
||||||
|
|
||||||
|
fun getLocalTimeUsingFactoryOfMethod(hour: Int, min: Int, seconds: Int): LocalTime {
|
||||||
|
return LocalTime.of(hour, min, seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalTimeUsingParseMethod(timeRepresentation: String): LocalTime {
|
||||||
|
return LocalTime.parse(timeRepresentation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalTimeFromClock(): LocalTime {
|
||||||
|
return LocalTime.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAnHour(localTime: LocalTime): LocalTime {
|
||||||
|
return localTime.plus(1, ChronoUnit.HOURS)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHourFromLocalTime(localTime: LocalTime): Int {
|
||||||
|
return localTime.hour
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalTimeWithMinuteSetToValue(localTime: LocalTime, minute: Int): LocalTime {
|
||||||
|
return localTime.withMinute(minute)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.Period
|
||||||
|
|
||||||
|
class UsePeriod {
|
||||||
|
|
||||||
|
fun modifyDates(localDate: LocalDate, period: Period): LocalDate {
|
||||||
|
return localDate.plus(period)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDifferenceBetweenDates(localDate1: LocalDate, localDate2: LocalDate): Period {
|
||||||
|
return Period.between(localDate1, localDate2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.datetime
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.ZonedDateTime
|
||||||
|
|
||||||
|
class UseZonedDateTime {
|
||||||
|
|
||||||
|
fun getZonedDateTime(localDateTime: LocalDateTime, zoneId: ZoneId): ZonedDateTime {
|
||||||
|
return ZonedDateTime.of(localDateTime, zoneId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.kotlin.datetime
|
||||||
|
|
||||||
|
import com.baeldung.datetime.UseLocalDateTime
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalTime
|
||||||
|
import java.time.Month
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
|
||||||
|
class UseLocalDateTimeUnitTest {
|
||||||
|
|
||||||
|
var useLocalDateTime = UseLocalDateTime()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenString_whenUsingParse_thenLocalDateTime() {
|
||||||
|
assertEquals(LocalDate.of(2016, Month.MAY, 10), useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30")
|
||||||
|
.toLocalDate())
|
||||||
|
assertEquals(LocalTime.of(6, 30), useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30")
|
||||||
|
.toLocalTime())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.kotlin.datetime
|
||||||
|
|
||||||
|
import com.baeldung.datetime.UseLocalDate
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import java.time.DayOfWeek
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
class UseLocalDateUnitTest {
|
||||||
|
|
||||||
|
var useLocalDate = UseLocalDate()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenValues_whenUsingFactoryOf_thenLocalDate() {
|
||||||
|
Assert.assertEquals("2016-05-10", useLocalDate.getLocalDateUsingFactoryOfMethod(2016, 5, 10)
|
||||||
|
.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenString_whenUsingParse_thenLocalDate() {
|
||||||
|
Assert.assertEquals("2016-05-10", useLocalDate.getLocalDateUsingParseMethod("2016-05-10")
|
||||||
|
.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenUsingClock_thenLocalDate() {
|
||||||
|
Assert.assertEquals(LocalDate.now(), useLocalDate.getLocalDateFromClock())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenDate_whenUsingPlus_thenNextDay() {
|
||||||
|
Assert.assertEquals(LocalDate.now()
|
||||||
|
.plusDays(1), useLocalDate.getNextDay(LocalDate.now()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenDate_whenUsingMinus_thenPreviousDay() {
|
||||||
|
Assert.assertEquals(LocalDate.now()
|
||||||
|
.minusDays(1), useLocalDate.getPreviousDay(LocalDate.now()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenToday_whenUsingGetDayOfWeek_thenDayOfWeek() {
|
||||||
|
Assert.assertEquals(DayOfWeek.SUNDAY, useLocalDate.getDayOfWeek(LocalDate.parse("2016-05-22")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenToday_whenUsingWithTemporalAdjuster_thenFirstDayOfMonth() {
|
||||||
|
Assert.assertEquals(1, useLocalDate.getFirstDayOfMonth()
|
||||||
|
.dayOfMonth.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenLocalDate_whenUsingAtStartOfDay_thenReturnMidnight() {
|
||||||
|
Assert.assertEquals(LocalDateTime.parse("2016-05-22T00:00:00"), useLocalDate.getStartOfDay(LocalDate.parse("2016-05-22")))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.baeldung.kotlin.datetime
|
||||||
|
|
||||||
|
import com.baeldung.datetime.UseLocalTime
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class UseLocalTimeUnitTest {
|
||||||
|
|
||||||
|
internal var useLocalTime = UseLocalTime()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenValues_whenUsingFactoryOf_thenLocalTime() {
|
||||||
|
Assert.assertEquals("07:07:07", useLocalTime.getLocalTimeUsingFactoryOfMethod(7, 7, 7).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenString_whenUsingParse_thenLocalTime() {
|
||||||
|
Assert.assertEquals("06:30", useLocalTime.getLocalTimeUsingParseMethod("06:30").toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenTime_whenAddHour_thenLocalTime() {
|
||||||
|
Assert.assertEquals("07:30", useLocalTime.addAnHour(LocalTime.of(6, 30)).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getHourFromLocalTime() {
|
||||||
|
Assert.assertEquals(1, useLocalTime.getHourFromLocalTime(LocalTime.of(1, 1)).toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getLocalTimeWithMinuteSetToValue() {
|
||||||
|
Assert.assertEquals(LocalTime.of(10, 20), useLocalTime.getLocalTimeWithMinuteSetToValue(LocalTime.of(10, 10), 20))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.kotlin.datetime
|
||||||
|
|
||||||
|
import com.baeldung.datetime.UsePeriod
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.Period
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class UsePeriodUnitTest {
|
||||||
|
|
||||||
|
var usingPeriod = UsePeriod()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenPeriodAndLocalDate_thenCalculateModifiedDate() {
|
||||||
|
val period = Period.ofDays(1)
|
||||||
|
val localDate = LocalDate.parse("2007-05-10")
|
||||||
|
Assert.assertEquals(localDate.plusDays(1), usingPeriod.modifyDates(localDate, period))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenDates_thenGetPeriod() {
|
||||||
|
val localDate1 = LocalDate.parse("2007-05-10")
|
||||||
|
val localDate2 = LocalDate.parse("2007-05-15")
|
||||||
|
|
||||||
|
Assert.assertEquals(Period.ofDays(5), usingPeriod.getDifferenceBetweenDates(localDate1, localDate2))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.kotlin.datetime
|
||||||
|
|
||||||
|
import com.baeldung.datetime.UseZonedDateTime
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
|
||||||
|
class UseZonedDateTimeUnitTest {
|
||||||
|
|
||||||
|
internal var zonedDateTime = UseZonedDateTime()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenZoneId_thenZonedDateTime() {
|
||||||
|
val zoneId = ZoneId.of("Europe/Paris")
|
||||||
|
val zonedDatetime = zonedDateTime.getZonedDateTime(LocalDateTime.parse("2016-05-20T06:30"), zoneId)
|
||||||
|
Assert.assertEquals(zoneId, ZoneId.from(zonedDatetime))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Introduction to Drools](http://www.baeldung.com/drools)
|
- [Introduction to Drools](http://www.baeldung.com/drools)
|
||||||
- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
||||||
- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
|
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>drools-backward-chaining</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>drools-backward-chaining</name>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<runtime.version>6.4.0.Final</runtime.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.kie</groupId>
|
|
||||||
<artifactId>kie-api</artifactId>
|
|
||||||
<version>${runtime.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.drools</groupId>
|
|
||||||
<artifactId>drools-core</artifactId>
|
|
||||||
<version>${runtime.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.drools</groupId>
|
|
||||||
<artifactId>drools-decisiontables</artifactId>
|
|
||||||
<version>${runtime.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.baeldung;
|
|
||||||
|
|
||||||
import org.kie.api.KieServices;
|
|
||||||
import org.kie.api.runtime.KieContainer;
|
|
||||||
import org.kie.api.runtime.KieSession;
|
|
||||||
|
|
||||||
import com.baeldung.model.Beatle;
|
|
||||||
|
|
||||||
public class BackwardChainingBeatles {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
KieServices ks = KieServices.Factory.get();
|
|
||||||
KieContainer kContainer = ks.getKieClasspathContainer();
|
|
||||||
KieSession kSession = kContainer.newKieSession("ksession-backward-chaining");
|
|
||||||
// drools session base on the xml configuration (<strong>kmodule.xml</strong>)
|
|
||||||
|
|
||||||
// graph population
|
|
||||||
kSession.insert(new Beatle("Starr", "drums"));
|
|
||||||
kSession.insert(new Beatle("McCartney", "bass"));
|
|
||||||
kSession.insert(new Beatle("Lennon", "guitar"));
|
|
||||||
kSession.insert(new Beatle("Harrison", "guitar"));
|
|
||||||
|
|
||||||
kSession.insert("Ringo"); // invoke the rule that calls the query implentation of backward chaining
|
|
||||||
kSession.fireAllRules(); // invoke all the rules
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package com.baeldung.model;
|
|
||||||
|
|
||||||
import org.kie.api.definition.type.Position;
|
|
||||||
|
|
||||||
public class Beatle {
|
|
||||||
|
|
||||||
@Position(0)
|
|
||||||
private String lastName;
|
|
||||||
@Position(1)
|
|
||||||
private String instrument;
|
|
||||||
|
|
||||||
public Beatle(String lastName, String instrument) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
this.instrument = instrument;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInstrument() {
|
|
||||||
return instrument;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInstrument(String instrument) {
|
|
||||||
this.instrument = instrument;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
|
|
||||||
<kbase name="backward_chaining" packages="backward_chaining">
|
|
||||||
<ksession name="ksession-backward-chaining"/>
|
|
||||||
</kbase>
|
|
||||||
</kmodule>
|
|
|
@ -1,44 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import com.baeldung.model.Beatle;
|
|
||||||
|
|
||||||
|
|
||||||
query whichBeatle(String lastName, String instrument)
|
|
||||||
Beatle(lastName, instrument;)
|
|
||||||
or
|
|
||||||
(Beatle(lastName, null;)
|
|
||||||
and
|
|
||||||
whichBeatle(null, instrument;)) //recursive call to the function that allows to search in a derivation tree structure
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "Ringo"
|
|
||||||
when
|
|
||||||
String(this == "Ringo")
|
|
||||||
whichBeatle("Starr", "drums";)
|
|
||||||
then
|
|
||||||
System.out.println("The beatle is Ringo Starr");
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "Paul"
|
|
||||||
when
|
|
||||||
String(this == "Paul")
|
|
||||||
whichBeatle("McCartney", "bass";)
|
|
||||||
then
|
|
||||||
System.out.println("The beatle is Paul McCartney");
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "John"
|
|
||||||
when
|
|
||||||
String(this == "John")
|
|
||||||
whichBeatle("Lennon", "guitar";)
|
|
||||||
then
|
|
||||||
System.out.println("The beatle is John Lennon");
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "George"
|
|
||||||
when
|
|
||||||
String(this == "George")
|
|
||||||
whichBeatle("Harrison", "guitar";)
|
|
||||||
then
|
|
||||||
System.out.println("The beatle is George Harrison");
|
|
||||||
end
|
|
|
@ -1,24 +1,19 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>drools</artifactId>
|
<artifactId>drools</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
<properties>
|
||||||
<properties>
|
<http-component-version>4.4.6</http-component-version>
|
||||||
<http-component-version>4.4.6</http-component-version>
|
<drools-version>7.4.1.Final</drools-version>
|
||||||
<drools-version>7.1.0.Beta2</drools-version>
|
<apache-poi-version>3.13</apache-poi-version>
|
||||||
<apache-poi-version>3.13</apache-poi-version>
|
</properties>
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -68,4 +63,25 @@
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<forkCount>3</forkCount>
|
||||||
|
<reuseForks>true</reuseForks>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*IntegrationTest.java</exclude>
|
||||||
|
<exclude>**/*LongRunningUnitTest.java</exclude>
|
||||||
|
<exclude>**/*ManualTest.java</exclude>
|
||||||
|
<exclude>**/JdbcTest.java</exclude>
|
||||||
|
<exclude>**/*LiveTest.java</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.drools.backward_chaining;
|
||||||
|
|
||||||
|
import org.kie.api.runtime.KieSession;
|
||||||
|
|
||||||
|
import com.baeldung.drools.config.DroolsBeanFactory;
|
||||||
|
import com.baeldung.drools.model.Fact;
|
||||||
|
import com.baeldung.drools.model.Result;
|
||||||
|
|
||||||
|
public class BackwardChaining {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Result result = new BackwardChaining().backwardChaining();
|
||||||
|
System.out.println(result.getValue());
|
||||||
|
result.getFacts()
|
||||||
|
.stream()
|
||||||
|
.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result backwardChaining() {
|
||||||
|
Result result = new Result();
|
||||||
|
KieSession ksession = new DroolsBeanFactory().getKieSession();
|
||||||
|
ksession.setGlobal("result", result);
|
||||||
|
ksession.insert(new Fact("Asia", "Planet Earth"));
|
||||||
|
ksession.insert(new Fact("China", "Asia"));
|
||||||
|
ksession.insert(new Fact("Great Wall of China", "China"));
|
||||||
|
|
||||||
|
ksession.fireAllRules();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ package com.baeldung.drools.config;
|
||||||
import org.drools.decisiontable.DecisionTableProviderImpl;
|
import org.drools.decisiontable.DecisionTableProviderImpl;
|
||||||
import org.kie.api.KieServices;
|
import org.kie.api.KieServices;
|
||||||
import org.kie.api.builder.*;
|
import org.kie.api.builder.*;
|
||||||
import org.kie.api.io.KieResources;
|
|
||||||
import org.kie.api.io.Resource;
|
import org.kie.api.io.Resource;
|
||||||
import org.kie.api.runtime.KieContainer;
|
import org.kie.api.runtime.KieContainer;
|
||||||
import org.kie.api.runtime.KieSession;
|
import org.kie.api.runtime.KieSession;
|
||||||
|
@ -22,7 +21,7 @@ public class DroolsBeanFactory {
|
||||||
|
|
||||||
private KieFileSystem getKieFileSystem() throws IOException{
|
private KieFileSystem getKieFileSystem() throws IOException{
|
||||||
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
|
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
|
||||||
List<String> rules=Arrays.asList("SuggestApplicant.drl","Product_rules.xls");
|
List<String> rules=Arrays.asList("BackwardChaining.drl","SuggestApplicant.drl","Product_rules.xls");
|
||||||
for(String rule:rules){
|
for(String rule:rules){
|
||||||
kieFileSystem.write(ResourceFactory.newClassPathResource(rule));
|
kieFileSystem.write(ResourceFactory.newClassPathResource(rule));
|
||||||
}
|
}
|
||||||
|
@ -56,9 +55,11 @@ public class DroolsBeanFactory {
|
||||||
getKieRepository();
|
getKieRepository();
|
||||||
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
|
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
|
||||||
|
|
||||||
|
kieFileSystem.write(ResourceFactory.newClassPathResource("com/baeldung/drools/rules/BackwardChaining.drl"));
|
||||||
kieFileSystem.write(ResourceFactory.newClassPathResource("com/baeldung/drools/rules/SuggestApplicant.drl"));
|
kieFileSystem.write(ResourceFactory.newClassPathResource("com/baeldung/drools/rules/SuggestApplicant.drl"));
|
||||||
kieFileSystem.write(ResourceFactory.newClassPathResource("com/baeldung/drools/rules/Product_rules.xls"));
|
kieFileSystem.write(ResourceFactory.newClassPathResource("com/baeldung/drools/rules/Product_rules.xls"));
|
||||||
|
|
||||||
|
|
||||||
KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);
|
KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);
|
||||||
kb.buildAll();
|
kb.buildAll();
|
||||||
KieModule kieModule = kb.getKieModule();
|
KieModule kieModule = kb.getKieModule();
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.baeldung.drools.model;
|
||||||
|
|
||||||
|
import org.kie.api.definition.type.Position;
|
||||||
|
|
||||||
|
public class Fact {
|
||||||
|
|
||||||
|
@Position(0)
|
||||||
|
private String element;
|
||||||
|
|
||||||
|
@Position(1)
|
||||||
|
private String place;
|
||||||
|
|
||||||
|
public Fact(String element, String place) {
|
||||||
|
this.element = element;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getElement() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElement(String element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlace() {
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlace(String place) {
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((element == null) ? 0 : element.hashCode());
|
||||||
|
result = prime * result + ((place == null) ? 0 : place.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;
|
||||||
|
Fact other = (Fact) obj;
|
||||||
|
if (element == null) {
|
||||||
|
if (other.element != null)
|
||||||
|
return false;
|
||||||
|
} else if (!element.equals(other.element))
|
||||||
|
return false;
|
||||||
|
if (place == null) {
|
||||||
|
if (other.place != null)
|
||||||
|
return false;
|
||||||
|
} else if (!place.equals(other.place))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Fact{" + "element='" + element + '\'' + ", place='" + place + '\'' + '}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.drools.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Result {
|
||||||
|
private String value;
|
||||||
|
private List<String> facts = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFacts() {
|
||||||
|
return facts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFacts(List<String> facts) {
|
||||||
|
this.facts = facts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFact(String fact) {
|
||||||
|
this.facts.add(fact);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.drools.rules
|
||||||
|
|
||||||
|
import com.baeldung.drools.model.Fact;
|
||||||
|
|
||||||
|
global com.baeldung.drools.model.Result result;
|
||||||
|
|
||||||
|
dialect "mvel"
|
||||||
|
|
||||||
|
query belongsTo(String x, String y)
|
||||||
|
Fact(x, y;)
|
||||||
|
or
|
||||||
|
(Fact(z, y;) and belongsTo(x, z;))
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Great Wall of China BELONGS TO Planet Earth"
|
||||||
|
when
|
||||||
|
belongsTo("Great Wall of China", "Planet Earth";)
|
||||||
|
then
|
||||||
|
result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth");
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "print all facts"
|
||||||
|
when
|
||||||
|
belongsTo(element, place;)
|
||||||
|
then
|
||||||
|
result.addFact(element + " IS ELEMENT OF " + place);
|
||||||
|
end
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.drools.backward_chaining;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.kie.api.runtime.KieSession;
|
||||||
|
|
||||||
|
import com.baeldung.drools.config.DroolsBeanFactory;
|
||||||
|
import com.baeldung.drools.model.Fact;
|
||||||
|
import com.baeldung.drools.model.Result;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
|
public class BackwardChainingTest {
|
||||||
|
private Result result;
|
||||||
|
private KieSession ksession;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
result = new Result();
|
||||||
|
ksession = new DroolsBeanFactory().getKieSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenWallOfChinaIsGiven_ThenItBelongsToPlanetEarth() {
|
||||||
|
|
||||||
|
ksession.setGlobal("result", result);
|
||||||
|
ksession.insert(new Fact("Asia", "Planet Earth"));
|
||||||
|
ksession.insert(new Fact("China", "Asia"));
|
||||||
|
ksession.insert(new Fact("Great Wall of China", "China"));
|
||||||
|
|
||||||
|
ksession.fireAllRules();
|
||||||
|
|
||||||
|
// Assert Decision one
|
||||||
|
assertEquals(result.getValue(), "Decision one taken: Great Wall of China BELONGS TO Planet Earth");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.ejb.EJB;
|
import javax.ejb.EJB;
|
||||||
|
@ -15,7 +16,6 @@ import wildfly.beans.UserBeanLocal;
|
||||||
* Servlet implementation class TestEJBServlet
|
* Servlet implementation class TestEJBServlet
|
||||||
*/
|
*/
|
||||||
public class TestEJBServlet extends HttpServlet {
|
public class TestEJBServlet extends HttpServlet {
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@EJB
|
@EJB
|
||||||
private UserBeanLocal userBean;
|
private UserBeanLocal userBean;
|
||||||
|
@ -23,8 +23,19 @@ public class TestEJBServlet extends HttpServlet {
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
List<User> users = userBean.getUsers();
|
List<User> users = userBean.getUsers();
|
||||||
|
|
||||||
response.getWriter()
|
PrintWriter out = response.getWriter();
|
||||||
.append("The number of users is: " + users.size());
|
|
||||||
|
out.println("<html>");
|
||||||
|
out.println("<head><title>Users</title></head>");
|
||||||
|
out.println("<body>");
|
||||||
|
out.println("<center><h1>List of users:</h1>");
|
||||||
|
out.println("<table border=\"1\" align=\"center\" style=\"width:50%\">");
|
||||||
|
for (User user : users) {
|
||||||
|
out.println("<tr>");
|
||||||
|
out.print("<td>" + user.getUsername() + "</td>");
|
||||||
|
out.print("<td>" + user.getEmail() + "</td>");
|
||||||
|
out.println("</tr>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
|
|
@ -3,7 +3,13 @@
|
||||||
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://xmlns.jcp.org/xml/ns/persistence" 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_1.xsd">
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
|
||||||
<persistence-unit name="wildfly-jpa" transaction-type="JTA">
|
<persistence-unit name="wildfly-jpa" transaction-type="JTA">
|
||||||
<jta-data-source>java:/PostgresDS</jta-data-source>
|
<jta-data-source>java:/H2DS</jta-data-source>
|
||||||
<class>model.User</class>
|
<class>model.User</class>
|
||||||
|
<properties>
|
||||||
|
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
|
||||||
|
<property name="hibernate.show_sql" value="true" />
|
||||||
|
<property name="hibernate.hbm2ddl.auto" value="create" />
|
||||||
|
<property name="hibernate.hbm2ddl.import_files" value="data.sql" />
|
||||||
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
INSERT INTO users (username, email, postal_number) VALUES ('user1', 'user1@baeldung.com', 1000), ('user2', 'user2@baeldung.com', 2);
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
## Guava Modules
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>guava18</artifactId>
|
<artifactId>guava-18</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue