/**
* Copyright (c) 2015 The original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.reveno.atp.examples;
import org.reveno.atp.api.Reveno;
import org.reveno.atp.api.commands.CommandContext;
import org.reveno.atp.api.transaction.TransactionContext;
import org.reveno.atp.core.Engine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Currency;
import java.util.concurrent.ExecutionException;
public class SimpleBankingAccount {
public static Reveno init(String folder) {
Reveno reveno = new Engine(folder);
reveno.domain().command(AddToBalanceCommand.class, AddToBalanceCommand::handler);
reveno.domain().command(CreateAccount.class, Long.class, CreateAccount::handler);
reveno.domain().transactionAction(AddToBalance.class, AddToBalance::handler);
reveno.domain().transactionAction(CreateAccount.class, CreateAccount::handler);
reveno.domain().viewMapper(Account.class, AccountView.class, (id, e, r) -> new AccountView(id, e.name, e.balance));
return reveno;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Reveno reveno = init(args[0]);
reveno.startup();
long id = reveno.executeSync(new CreateAccount("John", Currency.getInstance("EUR")));
reveno.executeSync(new AddToBalanceCommand(id, 10000, Currency.getInstance("USD")));
printStats(reveno, id);
reveno.shutdown();
reveno = init(args[0]);
reveno.startup();
printStats(reveno, id);
reveno.shutdown();
}
protected static void printStats(Reveno reveno, long id) {
LOG.info("Balance of Account {}: {}", id, reveno.query().find(AccountView.class, id).balance);
}
/**
* In current example it pays role of both Command and Transaction Action.
*/
public static class CreateAccount {
public long id;
public final String name;
public final Currency currency;
/*
* Command handler.
*
* Much better to replace this with DSL -> see SimpleBankingAccountDSL
*/
public static long handler(CreateAccount cmd, CommandContext ctx) {
cmd.id = ctx.id(Account.class);
ctx.executeTxAction(cmd);
return cmd.id;
}
/*
* Transaction Action handler.
*
* Much better to replace this with DSL -> see SimpleBankingAccountDSL
*/
public static void handler(CreateAccount tx, TransactionContext ctx) {
ctx.repo().store(tx.id, new Account(tx.name, 0, tx.currency));
}
public CreateAccount(String name, Currency currency) {
this.name = name;
this.currency = currency;
}
}
public static class AddToBalanceCommand {
public final long accountId;
public final long amount;
public final Currency currency;
public static void handler(AddToBalanceCommand cmd, CommandContext ctx) {
if (!ctx.repo().has(Account.class, cmd.accountId)) {
throw new RuntimeException(String.format("Account %s wasn't found!", cmd.accountId));
}
Account account = ctx.repo().get(Account.class, cmd.accountId);
ctx.executeTxAction(new AddToBalance(cmd.accountId, converter.convert(cmd.currency, account.currency, cmd.amount)));
}
public AddToBalanceCommand(long accountId, long amount, Currency currency) {
this.accountId = accountId;
this.amount = amount;
this.currency = currency;
}
protected static final CurrencyConverter converter = new DumbCurrencyConverter();
}
public static class AddToBalance {
public final long accountId;
public final long amount;
public static void handler(AddToBalance tx, TransactionContext ctx) {
ctx.repo().remap(tx.accountId, Account.class, (id, a) -> a.add(tx.amount));
}
public AddToBalance(long accountId, long amount) {
this.accountId = accountId;
this.amount = amount;
}
}
protected static final Logger LOG = LoggerFactory.getLogger(SimpleBankingAccount.class);
public interface CurrencyConverter {
long convert(Currency from, Currency to, long amount);
}
public static class DumbCurrencyConverter implements CurrencyConverter {
@Override
public long convert(Currency from, Currency to, long amount) {
if (from.getCurrencyCode().equals("USD") && to.getCurrencyCode().equals("EUR")) {
return (long) (amount * 0.8822);
}
return amount;
}
}
}