package name.abuchen.portfolio.datatransfer.pdf.dab;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import org.junit.Test;
import name.abuchen.portfolio.datatransfer.Extractor.BuySellEntryItem;
import name.abuchen.portfolio.datatransfer.Extractor.Item;
import name.abuchen.portfolio.datatransfer.Extractor.SecurityItem;
import name.abuchen.portfolio.datatransfer.Extractor.TransactionItem;
import name.abuchen.portfolio.datatransfer.actions.AssertImportActions;
import name.abuchen.portfolio.datatransfer.pdf.DABPDFExctractor;
import name.abuchen.portfolio.model.AccountTransaction;
import name.abuchen.portfolio.model.BuySellEntry;
import name.abuchen.portfolio.model.Client;
import name.abuchen.portfolio.model.PortfolioTransaction;
import name.abuchen.portfolio.model.Security;
import name.abuchen.portfolio.model.Transaction.Unit;
import name.abuchen.portfolio.money.CurrencyUnit;
import name.abuchen.portfolio.money.Money;
import name.abuchen.portfolio.money.Values;
@SuppressWarnings("nls")
public class DABPDFExtractorTest
{
private Security getSecurity(List<Item> results)
{
Optional<Item> item = results.stream().filter(i -> i instanceof SecurityItem).findFirst();
assertThat(item.isPresent(), is(true));
return ((SecurityItem) item.get()).getSecurity();
}
@Test
public void testWertpapierKauf() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABKauf.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("LU0360863863"));
assertThat(security.getName(), is("ARERO - Der Weltfonds Inhaber-Anteile o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 150_00L)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-01-06")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(0.91920)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, 0L)));
}
@Test
public void testWertpapierKauf2() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABKauf2.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("LU0274208692"));
assertThat(security.getName(), is("db x-tr.MSCI World Index ETF Inhaber-Anteile 1C o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 60_00)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-05-04")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(1.42270)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, 4_95L)));
}
@Test
public void testWertpapierKauf3() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABKauf3.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("LU0635178014"));
assertThat(security.getName(), is("ComSta.-MSCI Em.Mkts.TRN U.ETF Inhaber-Anteile I o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 325_00)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2016-01-04")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(10.9468)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, 0L)));
}
@Test
public void testWertpapierKauf4() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABKauf4.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("US8270481091"));
assertThat(security.getName(), is("Silgan Holdings Inc. Registered Shares DL -,01"));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.BUY));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(4798.86))));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-07-29")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(100)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, 0L)));
}
@Test
public void testWertpapierVerkauf() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABVerkauf.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("LU0392495700"));
assertThat(security.getName(), is("ComStage-MSCI USA TRN UCIT.ETF Inhaber-Anteile I o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 1994_12)));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-12-23")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(43)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.FEE), is(Money.of(CurrencyUnit.EUR, 10_09)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX),
is(Money.of(CurrencyUnit.EUR, 45_88 + 2_52 + 4_12)));
}
@Test
public void testWertpapierVerkauf2() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABVerkauf2.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("US8270481091"));
assertThat(security.getName(), is("Silgan Holdings Inc. Registered Shares DL -,01"));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(4465.12))));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-08-24")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(100)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(85.39 + 4.7))));
}
@Test
public void testWertpapierVerkauf3() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABVerkauf3.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("US8270481091"));
assertThat(security.getName(), is("Silgan Holdings Inc. Registered Shares DL -,01"));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof BuySellEntryItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(BuySellEntry.class));
BuySellEntry entry = (BuySellEntry) item.get().getSubject();
assertThat(entry.getPortfolioTransaction().getType(), is(PortfolioTransaction.Type.SELL));
assertThat(entry.getAccountTransaction().getType(), is(AccountTransaction.Type.SELL));
assertThat(entry.getPortfolioTransaction().getMonetaryAmount(),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(4447.21))));
assertThat(entry.getPortfolioTransaction().getDate(), is(LocalDate.parse("2015-08-24")));
assertThat(entry.getPortfolioTransaction().getShares(), is(Values.Share.factorize(100)));
assertThat(entry.getPortfolioTransaction().getUnitSum(Unit.Type.TAX),
is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(92.97 + 5.11))));
}
@Test
public void testDividend() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividend.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("DE0005660104"));
assertThat(security.getName(), is("EUWAX AG Inhaber-Aktien o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, 326_00)));
assertThat(transaction.getDate(), is(LocalDate.parse("2014-07-02")));
assertThat(transaction.getShares(), is(Values.Share.factorize(100)));
}
@Test
public void testDividendForeignCurrency() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividendForeignCurrency.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.USD);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("US7427181091"));
assertThat(security.getName(), is("Procter & Gamble Co., The Registered Shares o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.USD, 56_91)));
assertThat(transaction.getDate(), is(LocalDate.parse("2015-05-16")));
assertThat(transaction.getShares(), is(Values.Share.factorize(100)));
}
@Test
public void testDividendInForeignCurrencyButSecurityListedInEuro() throws IOException
{
Client client = new Client();
Security security = new Security();
security.setName("Procter & Gamble Co., The Registered Shares o.N.");
security.setIsin("US7427181091");
security.setCurrencyCode(CurrencyUnit.EUR);
client.addSecurity(security);
DABPDFExctractor extractor = new DABPDFExctractor(client)
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividendForeignCurrency.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(1));
new AssertImportActions().check(results, CurrencyUnit.USD);
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.USD, 56_91)));
assertThat(transaction.getDate(), is(LocalDate.parse("2015-05-16")));
assertThat(transaction.getShares(), is(Values.Share.factorize(100)));
}
@Test
public void testDividend3() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividend3.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("CH0012032048"));
assertThat(security.getName(), is("Roche Holding AG Inhaber-Genußscheineo.N."));
assertThat(security.getCurrencyCode(), is("CHF"));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(82.92))));
assertThat(transaction.getDate(), is(LocalDate.parse("2006-03-02")));
assertThat(transaction.getShares(), is(Values.Share.factorize(80)));
}
@Test
public void testDividend4() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividend4.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("US7033951036"));
assertThat(security.getName(), is("Patterson Companies Inc. Registered Shares DL -,01"));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.USD));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(80.92))));
assertThat(transaction.getDate(), is(LocalDate.parse("2016-07-29")));
assertThat(transaction.getShares(), is(Values.Share.factorize(500)));
}
@Test
public void testDividend5() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividend5.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("ZAE000042164"));
assertThat(security.getName(), is("MTN Group Ltd. Registered Shares RC -,0001"));
assertThat(security.getCurrencyCode(), is("ZAR"));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(586.80))));
assertThat(transaction.getDate(), is(LocalDate.parse("2015-03-30")));
assertThat(transaction.getShares(), is(Values.Share.factorize(1300)));
}
@Test
public void testDividend6() throws IOException
{
DABPDFExctractor extractor = new DABPDFExctractor(new Client())
{
@Override
protected String strip(File file) throws IOException
{
return from(file.getName());
}
};
List<Exception> errors = new ArrayList<Exception>();
List<Item> results = extractor.extract(Arrays.asList(new File("DABDividend6.txt")), errors);
assertThat(errors, empty());
assertThat(results.size(), is(2));
new AssertImportActions().check(results, CurrencyUnit.EUR);
// check security
Security security = getSecurity(results);
assertThat(security.getIsin(), is("DE0006483001"));
assertThat(security.getName(), is("Linde AG Inhaber-Aktien o.N."));
assertThat(security.getCurrencyCode(), is(CurrencyUnit.EUR));
// check buy sell transaction
Optional<Item> item = results.stream().filter(i -> i instanceof TransactionItem).findFirst();
assertThat(item.isPresent(), is(true));
assertThat(item.get().getSubject(), instanceOf(AccountTransaction.class));
AccountTransaction transaction = (AccountTransaction) item.get().getSubject();
assertThat(transaction.getType(), is(AccountTransaction.Type.DIVIDENDS));
assertThat(transaction.getSecurity(), is(security));
assertThat(transaction.getMonetaryAmount(), is(Money.of(CurrencyUnit.EUR, Values.Amount.factorize(198.79))));
assertThat(transaction.getDate(), is(LocalDate.parse("2013-05-31")));
assertThat(transaction.getShares(), is(Values.Share.factorize(100)));
}
private String from(String resource)
{
try (Scanner scanner = new Scanner(getClass().getResourceAsStream(resource), StandardCharsets.UTF_8.name()))
{
return scanner.useDelimiter("\\A").next();
}
}
}