File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
|||||||
|
package com.baeldung.lock;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.FileLock;
|
||||||
|
import java.nio.channels.NonReadableChannelException;
|
||||||
|
import java.nio.channels.NonWritableChannelException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
|
||||||
|
public class FileLocks {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(FileLocks.class);
|
||||||
|
|
||||||
|
// Write locks
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trying to get an exclusive lock on a read-only FileChannel won't work.
|
||||||
|
*/
|
||||||
|
static void getExclusiveLockFromInputStream() throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (FileInputStream fis = new FileInputStream(path.toFile());
|
||||||
|
FileLock lock = fis.getChannel()
|
||||||
|
.lock()) {
|
||||||
|
LOG.debug("This won't happen");
|
||||||
|
} catch (NonWritableChannelException e) {
|
||||||
|
LOG.error("The channel obtained through a FileInputStream isn't writable. You can't obtain an exclusive lock on it!");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an exclusive lock from a RandomAccessFile. Works because the file is writable.
|
||||||
|
* @param from beginning of the locked region
|
||||||
|
* @param size how many bytes to lock
|
||||||
|
* @return A lock object representing the newly-acquired lock
|
||||||
|
* @throws IOException if there is a problem creating the temporary file
|
||||||
|
*/
|
||||||
|
static FileLock getExclusiveLockFromRandomAccessFile(long from, long size) throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "rw");
|
||||||
|
FileLock lock = file.getChannel()
|
||||||
|
.lock(from, size, false)) {
|
||||||
|
if (lock.isValid()) {
|
||||||
|
LOG.debug("This is a valid exclusive lock");
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquires an exclusive lock on a file region.
|
||||||
|
* @param from beginning of the locked region
|
||||||
|
* @param size how many bytes to lock
|
||||||
|
* @return A lock object representing the newly-acquired lock
|
||||||
|
* @throws IOException if there is a problem creating the temporary file
|
||||||
|
*/
|
||||||
|
static FileLock getExclusiveLockFromFileChannelOpen(long from, long size) throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.APPEND); FileLock lock = channel.lock(from, size, false)) {
|
||||||
|
String text = "Hello, world.";
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(text.length() + System.lineSeparator()
|
||||||
|
.length());
|
||||||
|
buffer.put((text + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
|
||||||
|
buffer.flip();
|
||||||
|
while (buffer.hasRemaining()) {
|
||||||
|
channel.write(buffer, channel.size());
|
||||||
|
}
|
||||||
|
LOG.debug("This was written to the file");
|
||||||
|
Files.lines(path)
|
||||||
|
.forEach(LOG::debug);
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read locks
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trying to get a shared lock on a write-only FileChannel won't work.
|
||||||
|
*/
|
||||||
|
static void getReadLockFromOutputStream() throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (FileOutputStream fis = new FileOutputStream(path.toFile());
|
||||||
|
FileLock lock = fis.getChannel()
|
||||||
|
.lock(0, Long.MAX_VALUE, true)) {
|
||||||
|
LOG.debug("This won't happen");
|
||||||
|
} catch (NonReadableChannelException e) {
|
||||||
|
LOG.error("The channel obtained through a FileOutputStream isn't readable. " + "You can't obtain an shared lock on it!");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a lock from an <tt>InputStream</tt>.
|
||||||
|
* @param from beginning of the locked region
|
||||||
|
* @param size how many bytes to lock
|
||||||
|
* @return A lock object representing the newly-acquired lock
|
||||||
|
* @throws IOException if there is a problem creating the temporary file
|
||||||
|
*/
|
||||||
|
static FileLock getReadLockFromInputStream(long from, long size) throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (FileInputStream fis = new FileInputStream(path.toFile());
|
||||||
|
FileLock lock = fis.getChannel()
|
||||||
|
.lock(from, size, true)) {
|
||||||
|
if (lock.isValid()) {
|
||||||
|
LOG.debug("This is a valid shared lock");
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an exclusive lock from a RandomAccessFile. Works because the file is readable.
|
||||||
|
* @param from beginning of the locked region
|
||||||
|
* @param size how many bytes to lock
|
||||||
|
* @return A lock object representing the newly-acquired lock
|
||||||
|
* @throws IOException if there is a problem creating the temporary file
|
||||||
|
*/
|
||||||
|
static FileLock getReadLockFromRandomAccessFile(long from, long size) throws IOException {
|
||||||
|
Path path = Files.createTempFile("foo", "txt");
|
||||||
|
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "r"); // could also be "rw", but "r" is sufficient for reading
|
||||||
|
FileLock lock = file.getChannel()
|
||||||
|
.lock(from, size, true)) {
|
||||||
|
if (lock.isValid()) {
|
||||||
|
LOG.debug("This is a valid shared lock");
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package com.baeldung.lock;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.channels.FileLock;
|
||||||
|
import java.nio.channels.NonReadableChannelException;
|
||||||
|
import java.nio.channels.NonWritableChannelException;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class FileLocksUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAnInputStream_whenGetWriteLock_thenThrowNonWritableChannelException() {
|
||||||
|
assertThrows(NonWritableChannelException.class, () -> FileLocks.getExclusiveLockFromInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenARandomAccessFileWithReadWriteAccess_whenGetWriteLock_thenLock() throws IOException {
|
||||||
|
FileLock lock = FileLocks.getExclusiveLockFromRandomAccessFile(0, 10);
|
||||||
|
assertNotNull(lock);
|
||||||
|
assertFalse(lock.isShared());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAPath_whenGetExclusiveLock_thenLock() throws IOException {
|
||||||
|
FileLock lock = FileLocks.getExclusiveLockFromFileChannelOpen(0, 10);
|
||||||
|
assertNotNull(lock);
|
||||||
|
assertFalse(lock.isShared());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAFileOutputStream_whenGetSharedLock_thenThrowNonReadableChannelException() {
|
||||||
|
assertThrows(NonReadableChannelException.class, FileLocks::getReadLockFromOutputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAnInputStream_whenGetSharedLock_thenLock() throws IOException {
|
||||||
|
FileLock lock = FileLocks.getReadLockFromInputStream(0, 10);
|
||||||
|
assertNotNull(lock);
|
||||||
|
assertTrue(lock.isShared());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenARandomAccessFile_whenGetSharedLock_thenLock() throws IOException {
|
||||||
|
FileLock lock = FileLocks.getReadLockFromRandomAccessFile(0, 10);
|
||||||
|
assertNotNull(lock);
|
||||||
|
assertTrue(lock.isShared());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
|
- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
|
||||||
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
|
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
|
||||||
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
|
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
|
||||||
- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack)
|
- [Quick Guide to the Java Stack](http://www.baeldung.com/java-stack)
|
||||||
- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
|
- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
|
||||||
- [Introduction to Javadoc](http://www.baeldung.com/javadoc)
|
- [Introduction to Javadoc](http://www.baeldung.com/javadoc)
|
||||||
- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)
|
- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.baeldung;
|
package com.baeldung.timer;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -5,4 +5,5 @@ This module contains articles about Kotlin core features.
|
|||||||
### Relevant articles:
|
### Relevant articles:
|
||||||
- [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates)
|
- [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates)
|
||||||
- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator)
|
- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator)
|
||||||
|
- [Sequences in Kotlin](https://www.baeldung.com/kotlin/sequences)
|
||||||
- [[<-- Prev]](/core-kotlin-modules/core-kotlin)
|
- [[<-- Prev]](/core-kotlin-modules/core-kotlin)
|
||||||
|
|||||||
@@ -13,4 +13,7 @@ This module contains articles about Kotlin core features.
|
|||||||
- [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree)
|
- [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree)
|
||||||
- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin)
|
- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin)
|
||||||
- [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class)
|
- [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class)
|
||||||
|
- [Fuel HTTP Library with Kotlin](https://www.baeldung.com/kotlin-fuel)
|
||||||
|
- [Introduction to Kovenant Library for Kotlin](https://www.baeldung.com/kotlin-kovenant)
|
||||||
|
- [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt)
|
||||||
- [[More --> ]](/core-kotlin-modules/core-kotlin-2)
|
- [[More --> ]](/core-kotlin-modules/core-kotlin-2)
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ This module contains articles about Scala's core features
|
|||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [Introduction to Scala](https://www.baeldung.com/scala-intro)
|
- [Introduction to Scala](https://www.baeldung.com/scala-intro)
|
||||||
|
- [Regular Expressions in Scala](https://www.baeldung.com/scala/regular-expressions)
|
||||||
|
|||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
package com.baeldung.scala
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
||||||
|
class HigherOrderFunctionsExamplesUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingMapWithAnonymousFunction_thenTransformationIsApplied() = {
|
||||||
|
val expected = Seq("sir Alex Ferguson", "sir Bobby Charlton", "sir Frank Lampard")
|
||||||
|
|
||||||
|
val names = Seq("Alex Ferguson", "Bobby Charlton", "Frank Lampard")
|
||||||
|
val sirNames = names.map(name => "sir " + name)
|
||||||
|
|
||||||
|
assertEquals(expected, sirNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingMapWithDefined_thenTransformationIsApplied() = {
|
||||||
|
val expected = Seq("sir Alex Ferguson", "sir Bobby Charlton", "sir Frank Lampard")
|
||||||
|
|
||||||
|
val names = Seq("Alex Ferguson", "Bobby Charlton", "Frank Lampard")
|
||||||
|
|
||||||
|
def prefixWithSir(name: String) = "sir " + name
|
||||||
|
val sirNames = names.map(prefixWithSir)
|
||||||
|
|
||||||
|
assertEquals(expected, sirNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingFilter_thenUnecessaryElementsAreRemoved() = {
|
||||||
|
val expected = Seq("John O'Shea", "John Hartson")
|
||||||
|
|
||||||
|
val names = Seq("John O'Shea", "Aiden McGeady", "John Hartson")
|
||||||
|
val johns = names.filter(name => name.matches("^John .*"))
|
||||||
|
|
||||||
|
assertEquals(expected, johns)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingReduce_thenProperSumIsCalculated() = {
|
||||||
|
val expected = 2750
|
||||||
|
|
||||||
|
val earnings = Seq(1000, 1300, 450)
|
||||||
|
val sumEarnings = earnings.reduce((acc, x) => acc + x)
|
||||||
|
|
||||||
|
assertEquals(expected, sumEarnings)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingFold_thenNumberOfWordsShouldBeCalculated() = {
|
||||||
|
val expected = 6
|
||||||
|
|
||||||
|
val strings = Seq("bunch of words", "just me", "it")
|
||||||
|
val sumEarnings = strings.foldLeft(0)((acc, x) => acc + x.split(" ").size)
|
||||||
|
|
||||||
|
assertEquals(expected, sumEarnings)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def whenCallingOwnHigherOrderFunction_thenProperFunctionIsReturned() = {
|
||||||
|
def mathOperation(name: String): (Int, Int) => Int = (x: Int, y: Int) => {
|
||||||
|
name match {
|
||||||
|
case "addition" => x + y
|
||||||
|
case "multiplication" => x * y
|
||||||
|
case "division" => x/y
|
||||||
|
case "subtraction" => x - y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def add: (Int, Int) => Int = mathOperation("addition")
|
||||||
|
def mul: (Int, Int) => Int = mathOperation("multiplication")
|
||||||
|
def div: (Int, Int) => Int = mathOperation("division")
|
||||||
|
def sub: (Int, Int) => Int = mathOperation("subtraction")
|
||||||
|
|
||||||
|
assertEquals(15, add(10, 5))
|
||||||
|
assertEquals(50, mul(10, 5))
|
||||||
|
assertEquals(2, div(10, 5))
|
||||||
|
assertEquals(5, sub(10, 5))
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.scala
|
package com.baeldung.scala.regex
|
||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
@@ -19,6 +19,23 @@
|
|||||||
<artifactId>dsiutils</artifactId>
|
<artifactId>dsiutils</artifactId>
|
||||||
<version>${dsiutils.version}</version>
|
<version>${dsiutils.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vavr</groupId>
|
||||||
|
<artifactId>vavr</artifactId>
|
||||||
|
<version>${vavr.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${commons.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${assertj.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -33,6 +50,9 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<dsiutils.version>2.6.0</dsiutils.version>
|
<dsiutils.version>2.6.0</dsiutils.version>
|
||||||
|
<vavr.version>0.10.2</vavr.version>
|
||||||
|
<commons.version>3.9</commons.version>
|
||||||
|
<assertj.version>3.6.1</assertj.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
package com.baeldung.parsedouble;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import com.google.common.primitives.Doubles;
|
||||||
|
|
||||||
|
import io.vavr.control.Try;
|
||||||
|
|
||||||
|
public class StringToDoubleParserUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenParseStringToDouble_thenDefaultNaNValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble(null)).isNaN();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenParseStringToDouble_thenDefaultNaNValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble("")).isNaN();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenParseStringToDouble_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble("1")).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenParseStringToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble("1", 2.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenParseStringToDoubleWithDefault_thenDefaultValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble("", 1.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenParseStringToDoubleWithDefault_thenDefaultValueIsReturned() {
|
||||||
|
assertThat(parseStringToDouble(null, 1.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenParseStringToOptionalDouble_thenOptionalValueIsReturned() {
|
||||||
|
assertThat(parseStringToOptionalDouble("1")).isEqualTo(Optional.of(1.0d));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenParseStringToOptionalDouble_thenOptionalValueIsEmpty() {
|
||||||
|
assertThat(parseStringToOptionalDouble(null)).isEqualTo(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenParseStringToOptionalDouble_thenOptionalValueIsEmpty() {
|
||||||
|
assertThat(parseStringToOptionalDouble("")).isEqualTo(Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenParseStringToOptionalDouble_thenDefaulOptionalValueIsReturned() {
|
||||||
|
assertThat(parseStringToOptionalDouble("").orElse(1.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenParseStringToOptionalDouble_thenDefaulOptionalValueIsReturned() {
|
||||||
|
assertThat(parseStringToOptionalDouble(null).orElse(1.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenTryStringToDouble_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(tryStringToDouble("1", 2.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenTryStringToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(tryStringToDouble(null, 2.0d)).isEqualTo(2.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenTryStringToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(tryStringToDouble("", 2.0d)).isEqualTo(2.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTwoStringValues_whenTryParseFirstNonNull_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(Doubles.tryParse(MoreObjects.firstNonNull("1.0", "2.0"))).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullStringValue_whenTryParseFirstNonNull_thenSecondDoubleValueIsReturned() {
|
||||||
|
assertThat(Doubles.tryParse(MoreObjects.firstNonNull(null, "2.0"))).isEqualTo(2.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenTryParseFirstNonNull_thenNullIsReturned() {
|
||||||
|
assertThat(Doubles.tryParse(MoreObjects.firstNonNull("", "2.0"))).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenToDouble_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(NumberUtils.toDouble("1.0")).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenToDouble_thenLibraryDefaultDoubleValueIsReturned() {
|
||||||
|
String nullString = null;
|
||||||
|
assertThat(NumberUtils.toDouble(nullString)).isEqualTo(0.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenToDouble_thenLibraryDefaultDoubleValueIsReturned() {
|
||||||
|
assertThat(NumberUtils.toDouble("")).isEqualTo(0.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStringValue_whenToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(NumberUtils.toDouble("", 2.0d)).isEqualTo(2.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullValue_whenToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
String nullString = null;
|
||||||
|
assertThat(NumberUtils.toDouble(nullString, 2.0d)).isEqualTo(2.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringValue_whenToDoubleWithDefault_thenDoubleValueIsReturned() {
|
||||||
|
assertThat(NumberUtils.toDouble("1.0", 2.0d)).isEqualTo(1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Optional<Double> parseStringToOptionalDouble(String value) {
|
||||||
|
return value == null || value.isEmpty() ? Optional.empty() : Optional.of(Double.valueOf(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double parseStringToDouble(String value) {
|
||||||
|
return value == null || value.isEmpty() ? Double.NaN : Double.parseDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double parseStringToDouble(String value, double defaultValue) {
|
||||||
|
return value == null || value.isEmpty() ? defaultValue : Double.parseDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double tryStringToDouble(String value, double defaultValue) {
|
||||||
|
return Try.of(() -> Double.parseDouble(value)).getOrElse(defaultValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
-5
@@ -36,12 +36,12 @@
|
|||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>default-tools.jar</id>
|
<id>default-profile</id>
|
||||||
<activation>
|
<activation>
|
||||||
<property>
|
<activeByDefault>true</activeByDefault>
|
||||||
<name>java.vendor</name>
|
<file>
|
||||||
<value>Oracle Corporation</value>
|
<exists>${java.home}/../lib/tools.jar</exists>
|
||||||
</property>
|
</file>
|
||||||
</activation>
|
</activation>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -53,6 +53,24 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>mac-profile</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>false</activeByDefault>
|
||||||
|
<file>
|
||||||
|
<exists>${java.home}/../Classes/classes.jar</exists>
|
||||||
|
</file>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun</groupId>
|
||||||
|
<artifactId>tools</artifactId>
|
||||||
|
<version>${java.version}</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${java.home}/../Classes/classes.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package controllers;
|
||||||
|
|
||||||
|
import play.data.Form;
|
||||||
|
import play.data.FormFactory;
|
||||||
|
import play.mvc.Controller;
|
||||||
|
import play.mvc.Result;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
// Add the following to conf/routes
|
||||||
|
/*
|
||||||
|
GET /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Get
|
||||||
|
POST /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Post
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $model;format="Camel"$ form controller for Play Java
|
||||||
|
*/
|
||||||
|
public class $model;format="Camel"$Controller extends Controller {
|
||||||
|
|
||||||
|
private final Form<$model;format="Camel"$Data> $model;format="camel"$Form;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public $model;format="Camel"$Controller(FormFactory formFactory) {
|
||||||
|
this.$model;format="camel"$Form = formFactory.form($model;format="Camel"$Data.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result $model;format="camel"$Get() {
|
||||||
|
return ok(views.html.$model;format="camel"$.form.render($model;format="camel"$Form));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result $model;format="camel"$Post() {
|
||||||
|
Form<$model;format="Camel"$Data> boundForm = $model;format="camel"$Form.bindFromRequest();
|
||||||
|
if (boundForm.hasErrors()) {
|
||||||
|
return badRequest(views.html.$model;format="camel"$.form.render(boundForm));
|
||||||
|
} else {
|
||||||
|
$model;format="Camel"$Data $model;format="camel"$ = boundForm.get();
|
||||||
|
flash("success", "$model;format="Camel"$ " + $model;format="camel"$);
|
||||||
|
return redirect(routes.$model;format="Camel"$Controller.$model;format="camel"$Get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package controllers;
|
||||||
|
|
||||||
|
import play.data.validation.Constraints;
|
||||||
|
|
||||||
|
public class $model;format="Camel"$Data {
|
||||||
|
|
||||||
|
@Constraints.Required
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Constraints.Required
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
public $model;format="Camel"$Data() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(Integer age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("$model;format="Camel"$Data(%s, %s)", name, age);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
@($model;format="camel"$Form: Form[$model;format="Camel"$Data])
|
||||||
|
|
||||||
|
<h1>$model;format="camel"$ form</h1>
|
||||||
|
|
||||||
|
@flash.getOrDefault("success", "")
|
||||||
|
|
||||||
|
@helper.form(action = routes.$model;format="Camel"$Controller.$model;format="camel"$Post()) {
|
||||||
|
@helper.CSRF.formField
|
||||||
|
@helper.inputText($model;format="camel"$Form("name"))
|
||||||
|
@helper.inputText($model;format="camel"$Form("age"))
|
||||||
|
<input type="submit" value="submit"/>
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
description = Generates a Controller with form handling
|
||||||
|
model = user
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Temporary file until g8-scaffold will generate "test" directory
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package controllers;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import play.Application;
|
||||||
|
import play.filters.csrf.*;
|
||||||
|
import play.inject.guice.GuiceApplicationBuilder;
|
||||||
|
import play.mvc.*;
|
||||||
|
import play.test.WithApplication;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static play.mvc.Http.RequestBuilder;
|
||||||
|
import static play.mvc.Http.Status.OK;
|
||||||
|
import static play.test.Helpers.*;
|
||||||
|
import static play.api.test.CSRFTokenHelper.*;
|
||||||
|
|
||||||
|
public class $model;format="Camel"$ControllerTest extends WithApplication {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Application provideApplication() {
|
||||||
|
return new GuiceApplicationBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test$model;format="Camel"$Get() {
|
||||||
|
RequestBuilder request = new RequestBuilder()
|
||||||
|
.method(GET)
|
||||||
|
.uri("/$model;format="camel"$");
|
||||||
|
|
||||||
|
Result result = route(app, request);
|
||||||
|
assertEquals(OK, result.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test$model;format="Camel"$Post() {
|
||||||
|
HashMap<String, String> formData = new HashMap<>();
|
||||||
|
formData.put("name", "play");
|
||||||
|
formData.put("age", "4");
|
||||||
|
RequestBuilder request = addCSRFToken(new RequestBuilder()
|
||||||
|
.header(Http.HeaderNames.HOST, "localhost")
|
||||||
|
.method(POST)
|
||||||
|
.bodyForm(formData)
|
||||||
|
.uri("/$model;format="camel"$"));
|
||||||
|
|
||||||
|
Result result = route(app, request);
|
||||||
|
assertEquals(SEE_OTHER, result.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
logs
|
||||||
|
target
|
||||||
|
/.idea
|
||||||
|
/.idea_modules
|
||||||
|
/.classpath
|
||||||
|
/.project
|
||||||
|
/.settings
|
||||||
|
/RUNNING_PID
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package controllers;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import play.mvc.Controller;
|
||||||
|
import play.mvc.Http;
|
||||||
|
import play.mvc.Result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This controller contains an action to handle HTTP requests to the application's home page.
|
||||||
|
*/
|
||||||
|
public class HomeController extends Controller {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that renders an HTML page with a welcome message. The configuration in the
|
||||||
|
* <code>routes</code> file means that this method will be called when the application receives
|
||||||
|
* a
|
||||||
|
* <code>GET</code> request with a path of <code>/</code>.
|
||||||
|
*/
|
||||||
|
public Result index(Http.Request request) throws JsonProcessingException {
|
||||||
|
return ok(printStats(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String printStats(Http.Request request) throws JsonProcessingException {
|
||||||
|
Map<String, String[]> stringMap = request.body()
|
||||||
|
.asFormUrlEncoded();
|
||||||
|
Map<String, Object> map = ImmutableMap.of(
|
||||||
|
"Result", "ok",
|
||||||
|
"GetParams", request.queryString(),
|
||||||
|
"PostParams", stringMap == null ? Collections.emptyMap() : stringMap,
|
||||||
|
"Headers", request.getHeaders().toMap()
|
||||||
|
);
|
||||||
|
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@()
|
||||||
|
|
||||||
|
@main("Welcome to Play") {
|
||||||
|
<h1>Welcome to Play!</h1>
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@*
|
||||||
|
* This template is called from the `index` template. This template
|
||||||
|
* handles the rendering of the page header and body tags. It takes
|
||||||
|
* two arguments, a `String` for the title of the page and an `Html`
|
||||||
|
* object to insert into the body of the page.
|
||||||
|
*@
|
||||||
|
@(title: String)(content: Html)
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
@* Here's where we render the page title `String`. *@
|
||||||
|
<title>@title</title>
|
||||||
|
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
|
||||||
|
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
@* And here's where we render the `Html` object containing
|
||||||
|
* the page content. *@
|
||||||
|
@content
|
||||||
|
|
||||||
|
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
name := """async"""
|
||||||
|
organization := "com.example"
|
||||||
|
|
||||||
|
version := "1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
lazy val root = (project in file(".")).enablePlugins(PlayJava)
|
||||||
|
|
||||||
|
scalaVersion := "2.13.1"
|
||||||
|
|
||||||
|
// comment out the original line
|
||||||
|
libraryDependencies += guice
|
||||||
|
libraryDependencies += javaWs
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# This is the main configuration file for the application.
|
||||||
|
# https://www.playframework.com/documentation/latest/ConfigFile
|
||||||
|
play.ws.followRedirects=false
|
||||||
|
play.ws.useragent=MyPlayApplication
|
||||||
|
play.ws.compressionEnabled=true
|
||||||
|
# time to wait for the connection to be established
|
||||||
|
play.ws.timeout.connection=30.seconds
|
||||||
|
# time to wait for data after the connection is open
|
||||||
|
play.ws.timeout.idle=30.seconds
|
||||||
|
# max time available to complete the request
|
||||||
|
play.ws.timeout.request=300.seconds
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
|
||||||
|
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>${application.home:-.}/logs/application.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<appender-ref ref="FILE" />
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="play" level="INFO" />
|
||||||
|
<logger name="application" level="DEBUG" />
|
||||||
|
<logger name="controllers" level="DEBUG" />
|
||||||
|
|
||||||
|
<root level="WARN">
|
||||||
|
<appender-ref ref="ASYNCFILE" />
|
||||||
|
<appender-ref ref="ASYNCSTDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user