Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .mvn/wrapper/MavenWrapperDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.net.*;
import java.io.*;
import java.nio.channels.*;
Expand All @@ -25,7 +26,7 @@ public class MavenWrapperDownloader {
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";

/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
Expand Down Expand Up @@ -54,7 +55,7 @@ public static void main(String args[]) {
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Expand All @@ -65,7 +66,7 @@ public static void main(String args[]) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
Expand All @@ -76,8 +77,8 @@ public static void main(String args[]) {
System.out.println("- Downloading from: " + url);

File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
Expand Down
107 changes: 66 additions & 41 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,49 +1,74 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.crewmeister</groupId>
<artifactId>cm-coding-challenge</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cm-coding-challenge</name>
<description>The java coding challenge for developer candidates applying at Crewmeister</description>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.crewmeister</groupId>
<artifactId>cm-coding-challenge</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cm-coding-challenge</name>
<description>The java coding challenge for developer candidates applying at Crewmeister</description>

<properties>
<java.version>11</java.version>
</properties>
<properties>
<java.version>11</java.version>
<lombok.version>1.18.24</lombok.version>
<jacson.version>2.11.1</jacson.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jacson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jacson.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.crewmeister.cmcodingchallenge;
package com.crewmeister.cmcodingchallenge.currency;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CmCodingChallengeApplication {

public static void main(String[] args) {
SpringApplication.run(CmCodingChallengeApplication.class, args);
}

public static void main(String[] args) {
SpringApplication.run(CmCodingChallengeApplication.class, args);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.crewmeister.cmcodingchallenge.currency.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;

@Configuration
@EnableRetry
public class RestTemplateConfiguration {

@Value("${external.fx.timeout}")
private int timeout;

@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.defaultMessageConverters()
.setConnectTimeout(Duration.ofMillis(timeout))
.setReadTimeout(Duration.ofMillis(timeout))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.crewmeister.cmcodingchallenge.currency.constants;

import java.util.Arrays;
import java.util.Optional;

public enum Currency {
AUD("AUD"),
BGN("BGN"),
BRL("BRL"),
CAD("CAD"),
CHF("CHF"),
CNY("CNY"),
CYP("CYP"),
CZK("CZK"),
DKK("DKK"),
EEK("EEK"),
GBP("GBP"),
GRD("GRD"),
HKD("HKD"),
HRK("HRK"),
HUF("HUF"),
IDR("IDR"),
ILS("ILS"),
INR("INR"),
ISK("ISK"),
JPY("JPY"),
KRW("KRW"),
LTL("LTL"),
LVL("LVL"),
MTL("MTL"),
MXN("MXN"),
MYR("MYR"),
NOK("NOK"),
NZD("NZD"),
PHP("PHP"),
PLN("PLN"),
ROL("ROL"),
RON("RON"),
RUB("RUB"),
SEK("SEK"),
SGD("SGD"),
SIT("SIT"),
SKK("SKK"),
THB("THB"),
TRL("TRL"),
TRY("TRY"),
USD("USD"),
ZAR("ZAR");
private final String isoCode;

Currency(String isoCode) {
this.isoCode = isoCode;
}

public static Optional<Currency> getCurrency(String currencyCode) {
return Arrays.stream(values())
.filter(code -> code.isoCode.equalsIgnoreCase(currencyCode)).findFirst();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.crewmeister.cmcodingchallenge.currency.controller;

import com.crewmeister.cmcodingchallenge.currency.constants.Currency;
import com.crewmeister.cmcodingchallenge.currency.domain.internal.CurrencyConversionRates;
import com.crewmeister.cmcodingchallenge.currency.domain.internal.CurrencyResponse;
import com.crewmeister.cmcodingchallenge.currency.domain.internal.ExchangedAmount;
import com.crewmeister.cmcodingchallenge.currency.exception.CurrencyNotSupportedException;
import com.crewmeister.cmcodingchallenge.currency.exception.RateNotAvailableException;
import com.crewmeister.cmcodingchallenge.currency.service.FXRateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

@RestController()
@RequestMapping("/api")
public class CurrencyController {

@Autowired
private FXRateService fxRateService;

@GetMapping("/currencies")
public ResponseEntity<CurrencyResponse> getCurrencies() {
return new ResponseEntity<>(new CurrencyResponse(Currency.values()), HttpStatus.OK);
}

@GetMapping("/exchange-rates")
public ResponseEntity<CurrencyConversionRates> getExchangeRates(
@RequestParam() String currencyCode,
@RequestParam(required = false) String date
) {
CurrencyConversionRates rates = null;
try {
rates = fxRateService.getFXRates(currencyCode, date);
} catch (CurrencyNotSupportedException e) {
handleCurrencyNotSupportedException();
}
return new ResponseEntity<>(rates, HttpStatus.OK);
}

@GetMapping("/exchange-currency")
public ResponseEntity<ExchangedAmount> getCurrencyExchange(
@RequestParam() String currencyCode,
@RequestParam() String amount,
@RequestParam(required = false) String date

) {
ExchangedAmount exchangedAmount = null;
try {
exchangedAmount = fxRateService.getFXValue(currencyCode, amount, date);
} catch (CurrencyNotSupportedException e) {
handleCurrencyNotSupportedException();
} catch (RateNotAvailableException e) {
handleRateNotAvailableException();
}
return new ResponseEntity<>(exchangedAmount, HttpStatus.OK);
}

private void handleCurrencyNotSupportedException() {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Currency Not Supported");
}

private void handleRateNotAvailableException() {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Rate Not Available for the specified date");
}
}
Loading