NYLA Solutions Core
This Java API provides support for application utilities (application configuration,
data encryption, debugger, text processing and more).
This library is a collection of the
design pattern implementation.
Requirements
Benefits
- Lots of implemented design patterns and utilities
- Very cloud native friendly
- Default settings required ZERO additional runtime dependencies
- Used by some of the largest corporations in the US
Available in the maven central repository
See http://mvnrepository.com/artifact/com.github.nyla-solutions/nyla.solutions.core
Maven dependencies
<dependency>
<groupId>com.github.nyla-solutions</groupId>
<artifactId>nyla.solutions.core</artifactId>
<version>${VERSION}</version>
</dependency>
Add it using Maven
Gradle
compile group: 'com.github.nyla-solutions', name: 'nyla.solutions.core', version: $VERSION
Building
Download Gradle version 6.4.1 or higher
`gradle clean build`
Solutions Core Overview
Package: nyla.solutions.core.util.stats
Use the Mathematics object to calculate statistics
such as the 95th percentile, standard deviation,
variance, mean of
set of numbers, etc.
Example Code
Mathematics math = new Mathematics();
assertEquals(700,math.variance(10, 20, 60));
assertEquals(30,math.mean(10, 20, 60));
assertEquals(0.816496580927726,math.stdDev(9, 10, 11));
assertEquals(323,subject.percentile(95.0,10,232,232,323,232));
assertEquals(454,subject.percentile(95.0,23,75,19,3,5,454,100000,232,23,23,2,32,32,3,2,3,4,34,3,43,43,4,3,43,43,4,3,43,4,34,3,4,3,4343));
assertEquals(98,subject.percentile(95.0,23,1,23,2,32,3,2,356,56,5,6,57,6,8,9,8,98,9,8,12,1,2,1,21,21,21));
Package: nyla.solutions.core.util
Config
This class provides a central mechanism for applications to access key/value property settings and encrypted passwords. Developer can get access to environment variable, system Java properties and other property. It also supports type conversion from property strings to numbers, booleans and arrays. There are several ways to specify the configuration properties.
1. Add file config.properties to CLASSPATH. This file will be loaded as a Java resource bundle.
2. Add the JVM argument -Dconfig.properties where the value is equal to the location of the configuration file.
Example: -Dconfig.properties=/dev/configurations/files/system/config.properties
There are methods to get the String value property such as Config.config().getProperty(key) method. There are also methods to get an expected property value of a type such as Integer, Boolean, etc.
nyla.solutions.core.util.Config.mergeSystemProperties=false
It also supports formatting several property values into a single property by adding the following property;
nyla.solutions.core.util.Config.useFormatting=true
By default the configuration is read only once when the application is initialized. Add the following to the configuration property file to always reload the property whenever a getProperty... method is called. Note that this is a potentially an expensive operation.
nyla.solutions.core.util.Config.alwaysReloadProperties=true
Note the following is a property file used for the sample usage code below.
application.name=JUNIT
debug=true
nyla.solutions.core.util.ConfigTest.integerProperty=24
password={cryption}102 42 -22 24 12 66 -35 89 50 -15 21 9 -67 73 -128 -105
nyla.solutions.core.util.Config.mergeSystemProperties=true
nyla.solutions.core.util.Config.useFormatting=true
application.name.debug=${application.name}.${debug}.${user.dir}
USAGE
String property = Config.config().getProperty("application.name");
Assert.assertEquals("JUNIT",property);
try
{
property = Config.config().getProperty("missing.property");
}
catch(ConfigException e)
{
}
property = Config.config().getProperty("missing.property","default");
Assert.assertEquals("default", property);
boolean propertyBoolean = Config.config().getPropertyBoolean("debug");
Assert.assertTrue(propertyBoolean);
propertyBoolean = Config.config().getPropertyBoolean("missing.boolean.property",false);
Assert.assertFalse(propertyBoolean);
int integerProperty = Config.config().getPropertyInteger(nyla.solutions.core.util.ConfigTest.class, "integerProperty");
Assert.assertEquals(24, integerProperty);
char[] password = Config.config().getPropertyPassword("password");
Assert.assertNotNull(password);
String jvmSystemPropertyName = "user.dir";
property = Config.config().getProperty(jvmSystemPropertyName);
Assert.assertNotNull(property);
property = Config.config().getProperty("application.name.debug");
Debugger.println(this,"property="+property);
Assert.assertTrue("All values formatted:"+property, property.indexOf("${") < 0);
Supports observer pattern for file configuration changes.
Note that this requires two configuration properties.
| CONFIG_FILE_WATCH_POLLING_INTERVAL_MS | 1000 | true |
| CONFIG_FILE_WATCH_DELAY_MS | 10 | false (default is 5 seconds) |
File config = Paths.get("src/test/resources/config/configTest.properties").toFile();
System.setProperty(Config.SYS_PROPERTY, config.getAbsolutePath());
SubjectObserver<Settings> settingsObserver = new SubjectObserver<Settings>()
{
private String name = "test";
@Override
public String getId()
{
return name;
}
@Override
public void update(String subjectName, Settings data)
{
System.out.println("subjectNAme:"+subjectName+" data:"+data);
isCalled = true;
}
};
Config.registerObserver(settingsObserver);
IO.touch(config);
Cryption
Cryption provides a set of functions to encrypt and decrypt bytes and text. It uses the javax.crypto package.
The default encryption algorithm is the Advanced Encryption Standard (AES).
The default algorithm can be changed with a configuration property named nyla.solutions.core.util.Cryption.alogorithm.
# The following sets the encryption algorithm to Data Encryption Standard (DES)
nyla.solutions.core.util.Cryption.algorithm=DES
The Cryption object is used by nyla.solutions.core.util.Config object to decrypt properties prefixed with {cryption}. The Cryption class can be used to generate encrypted passwords that can be added to the config.properties file. The Cryption main method accepts a password and will print the encrypted password that can be added to the property file.
The printed password will be prefixed with the value “{cryption}”. Any properties prefixed with {cryption} in the config.properties is an indicator that content is encrypted.
The follow is a sample Cryption UNIX script:
java -classpath build/libs/nyla.solutions.core-2.0.0-SNAPSHOT.jar -DCRYPTION_KEY=CHANGEMEKEY nyla.solutions.core.util.Cryption MYPASSWORD
The following is a sample output of an encrypted password generated by the Cryption main method.
{cryption}23 4 -3 -77 -128 -88 -34 -105 23 4 -3 -77 -128 -88 -34 -105
USAGE
Cryption cryption = new Cryption();
String original = "Text to encrypt";
String encrypted = cryption.encryptText(original);
Assert.assertTrue(!original.equals(encrypted));
String decrypted = cryption.decryptText(encrypted);
Assert.assertEquals(decrypted, original);
byte[] orginalBytes = original.getBytes();
byte[] encryptedBytes = cryption.encrypt(orginalBytes);
byte[] decryptedBytes = cryption.decrypt(encryptedBytes);
Assert.assertTrue(Arrays.equals(orginalBytes, decryptedBytes));
byte[] keyBytes = {0x22, 0x15, 0x27, 0x36, 0x41, 0x11, 0x79, 0x76};
Cryption desCryption = new Cryption(keyBytes,"DES");
String desEncrypted = desCryption.encryptText(original);
Assert.assertTrue(!original.equals(encrypted) && !desEncrypted.equals(encrypted));
decrypted = desCryption.decryptText(desEncrypted);
Assert.assertEquals(decrypted, original);
Debugger
Debugger provides useful methods for obtaining exception stack traces. It can build reader friendly strings for objects that do not implement their toString method.
It also provides a set of print functions to log DEBUG, INFO, WARN and FATAL level messages using the Debugger.println(...), Debugger.printInfo(...),Debugger.printWarn(...) and Debugger.printFatal(...) methods respectively.
The default log object implementation is nyla.solutions.core.operations.Log4J.
Set the configuration property to plug-in another logger (@see Config more information);
nyla.solutions.core.util.Debugger.logClass=className
The logClass class name indicated must implement the nyla.solutions.core.operations.Log interface.
USAGE
String[] arraysNicely = { "first","second"};
String text = Debugger.toString(arraysNicely);
Assert.assertEquals("{[0]=first ,[1]=second}", text);
Debugger.printInfo("This is a INFO level message");
Debugger.println(this, "This is a DEBUG level message");
text = null;
try{
text.toString();
}
catch(NullPointerException e)
{
String stackTrace = Debugger.stackTrace(e);
Debugger.printWarn(this,stackTrace);
Debugger.printError(e);
Debugger.printFatal(this,"Stack trace will not be printed, because this is not an exception object.");
}
BeanComparator
BeanComparator is a generic Bean property java.util.Comparator implementation. It compares specified property beans using reflection. This object is internally used by the Organizer.sortByJavaBeanProperty(String,Collection) method.
USAGE
BeanComparator beanComparator = new BeanComparator("firstName");
UserProfile josiah = new UserProfile();
josiah.setFirstName("Josiah");
UserProfile nyla = new UserProfile();
nyla.setFirstName("Nyla");
Assert.assertTrue(beanComparator.compare(josiah, nyla) < 0);
ArrayList<UserProfile> unSorted = new ArrayList<UserProfile>();
unSorted.add(0, nyla);
unSorted.add(1, josiah);
beanComparator.setDescending(true);
beanComparator.sort(unSorted);
Assert.assertTrue(unSorted.get(0) == nyla);
beanComparator.setDescending(false);
beanComparator.sort(unSorted);
Assert.assertTrue(unSorted.get(0) == josiah);
Text
nyla.solutions.core.util.Text is geared toward string based processing. It includes template engine support like Free Marker that builds composite strings/values dynamically at runtime (see http://freemarker.sourceforge.net/). There are also methods to support complex regular expressions with Boolean AND, OR and NOT logic, numerous string conversions, general text manipulation and parsing methods.
Note that the default implementation uses the class
nyla.solutions.core.patterns.decorator.BasicTextStyles
To use Free Marker directory add a configuration properties
nyla.solutions.core.util.Text.textStyles=nyla.solutions.global.patterns.decorator.style.FreeMarkerTextStyles
Note: You must add the freemarker JARs to the classpath to use this implementation.
USAGE
String text = "${company} A2D2 Solution Global Application Testings";
Map<String,String> map = new HashMap<String,String>();
map.put("company", "MyCompany");
text = Text.formatText(text,map);
Assert.assertEquals("MyCompany Solution Global Application Testings", text);
Assert.assertTrue(Text.matches("Kenya Africa", ".*Kenya.*"));
Assert.assertFalse(Text.matches("Kenya", "${NOT}.*Kenya.*"));
Assert.assertTrue(Text.matches("Kenya", "${NOT}${NOT}.*Kenya.*"));
Assert.assertFalse(Text.matches("America, Kenya, Paris", ".*Paris.*${AND}.${NOT}.*Kenya.*"));
Assert.assertFalse(Text.matches("America, Kenya, Paris", "(.*Paris.*${AND}.${NOT}.*Kenya.*)${OR}(.*Paris.*${AND}.${NOT}.*Kenya.*)"));
Assert.assertTrue(Text.matches("United States, Kenya, France", "${NOT}.*America.*${AND}.*Kenya.${NOT}.*Paris.*"));
Assert.assertTrue(Text.matches("United States, Kenya, France", "${NOT}.*America.*${AND}.*Kenya.${NOT}.*Paris.*"));
String start = "Color:";
String end = ";";
Collection collection = Text.parse("Color:green; Weight:155oz; Color:Blue; Weight:23oz", start, end);
Assert.assertEquals(2,collection.size());
Iterator i = collection.iterator();
Assert.assertEquals("green", i.next());
Assert.assertEquals("Blue", i.next());
int count = Text.characterCount('A', "All Apples");
Assert.assertEquals(2, count);
count = Text.digitCount(text);
Assert.assertEquals(2, count);
String format = "#,###,###.###";
String formattedText = Text.formatNumber(123443243240.033423,format);
Assert.assertEquals("123,443,243,240.033",formattedText);
formattedText = Text.formatCurrency("1000.33");
Assert.assertEquals("$1,000.33",formattedText);
formattedText = Text.formatPercent("2.3");
Assert.assertEquals("2.3%",formattedText);
text = "Greg on line 1\nGreen on line two";
String results = Text.grepText("Green", text);
Assert.assertEquals("Green on line two",results);
PROXY
Use the nyla.solutions.core.util.PROXY method to execute methods generically.
Object response = PROXY.executeMethod(this, "verifyNoArgs", null);
assertNull(response);
assertTrue(verifyNoArgsCalled);
response = PROXY.executeMethod(this, "verifyWityArgs", Arrays.asList("test").toArray());
assertNull(response);
assertTrue(verifyWityArgs);
response = PROXY.executeMethod(this, "verifyWityArgsWithReturn", Arrays.asList("test").toArray());
assertEquals("test", response);
assertTrue(verifyWityArgsWithReturn);
void verifyNoArgs()
{
System.out.println("verifyNoArgs");
verifyNoArgsCalled = true;
}
void verifyWityArgs(String text)
{
System.out.println("verifyWityArgs:"+text);
verifyWityArgs = true;
}
String verifyWityArgsWithReturn(String text)
{
System.out.println("verifyWityArgsWithReturn:"+text);
verifyWityArgsWithReturn = true;
return text;
}
Package: nyla.solutions.core.util.stats
Use the Mathematics object to calculate statistics
such as the 95th percentile, standard deviation,
variance, mean of
set of numbers.
Example Code
Mathematics math = new Mathematics();
assertEquals(700,subject.variance(10, 20, 60));
assertEquals(30,subject.mean(10, 20, 60));
assertEquals(0.816496580927726,subject.stdDev(9, 10, 11));
assertEquals(323,subject.percentile(95.0,10,232,232,323,232));
assertEquals(454,subject.percentile(95.0,23,75,19,3,5,454,100000,232,23,23,2,32,32,3,2,3,4,34,3,43,43,4,3,43,43,4,3,43,4,34,3,4,3,4343));
assertEquals(98,subject.percentile(95.0,23,1,23,2,32,3,2,356,56,5,6,57,6,8,9,8,98,9,8,12,1,2,1,21,21,21));
IO
See package nyla.solutions.core.io
FileMonitor
You can use the nyla.solutions.core.io.FileMonitor observer pattern to
notify added SubjectObserver(s) of new or update files in given directory that match a file name patterns.
var subject = new FileMonitor(pollingIntervalMs, delayMs);
var expectedResults = new ArrayList<Boolean>();
SubjectObserver<FileEvent> observer = (observable, arg) -> {
System.out.println(" observable:"+observable+" arg:"+arg);
expectedResults.add(Boolean.TRUE);
};
subject.add(observer);
var processCurrentFiles = false;
subject.monitor("runtime", "*.txt", processCurrentFiles);
sleep(1000*2);
assertTrue(expectedResults.isEmpty());
IO.touch(Paths.get("runtime/FileMonitor.txt").toFile());
sleep(1000*2);
assertFalse(expectedResults.isEmpty());
Patterns
JDBC
See nyla.solutions.core.patterns.jdbc.
Getting a connection
String driver = Config.config().getProperty("test.sql.driver","org.h2.Driver");
String connectionURL = Config.config().getProperty("test.sql.connectionURL");
String user = Config.config().getProperty("test.sql.user");
char[] password = Config.config().getPropertyPassword("test.sql.password");
Connection connection = Sql.createConnection(driver,connectionURL,user,password);
Query with results as a Java Map
ResultSetToMapConverter converter = ...;
Map<String,?> actual = new Sql().queryForMap(connection,converter,sql);
Query with results as a Java Map using the default converter.
Map<String,?> actual = new Sql().queryForMap(connection,sql);
Execute a statement
new Sql().execute(connection,"insert into table values(1,2)");
query For a single Column value
int actualCount = new Sql().queryForColumn(connection,"select 3 from dual",1, Integer.class);
Batch Patterns
BatchJob
See nyla.solutions.core.patterns.batch.
The BatchJob class handles reading, processing and writing records in a batch fashion.
The readings, procesors and writers are based on
java.util.function.Supplier, java.util.function.Function and java.util.function.Consumer.
This allows this framework to be used with simple
Lamba expressions.
Sample usage.
BatchJob batchJob = BatchJob.builder().supplier(supplier)
.consumer(consumer)
.batchChunkSize(batchChunkSize).processor(
processor).build();
BatchReport batchRecord = batchJob.execute()
JdbcBatch
See package nyla.solutions.core.patterns.jdbc.batch
String sql = "select * from test";
PreparedStatementMapConsumer preparedStatementMapConsumer = new PreparedStatementMapConsumer(bindVariableInterpreter,preparedStatementCreator);
Map<String, Object> map = new HashMap<>();
SelectResultSetConverterSupplier resultSetSupplier = new SelectResultSetConverterSupplier(
() -> Sql.createConnection(driver,
connectionURL,
user, password),
new ResultSetToMapConverter(),
sql);
JdbcBatch jdbcBatch = new JdbcBatch(resultSetSupplier,
new ResultSetToMapConverter(),
preparedStatementMapConsumer,
batchChunkSize);
SQL Execute Update With Java Bean
Example Update
UserProfile expectedData = JavaBeanGeneratorCreator.of(UserProfile.class).create();
String sql = "insert into table_name(email,firstName) values (:email,:firstName)";
int actualCount = new Sql().executeUpdateSqlWithJavaBean(connection,sql,expectedData);
assertEquals(1,actualCount);
verify(preparedStatement).executeUpdate();
Search Patterns
See package nyla.solutions.core.patterns.search
ReLookup
ReLookup is a map that supports searching for values using a complex regular expression syntax. The key is a regular expression. This operation is similar to the lookup operation. The RELookup will iterate through the given expressions looking for a match on the corresponding source attribute. The value of the lookup is used if the regular expression matches the source attribute value.
- Complex Regular Expression (And/Not) *
By default, regular expressions do not have an easy way to chain expressions together using AND/NOT logic. The OR logical expression is supported with the character “|”. The RELookup operation combines regular expressions with a special syntax to support AND/NOT logic.
AND Operation
The RELookup supports chaining expressions together with “AND” logic. This is accomplished by chaining expressions together with “${AND}”. The string “${AND}” can be used to separate two regular expressions. If any of the regular expressions return false then the entire regular expression is false. In the following example, the regular expression “.USA.${AND}.Greece.”, only returns true if the text contains both “USA” and “Greece”.
| .USA.${AND}.Greece. | USA and Greece | True |
| .USA.${AND}.Greece. | USA | False |
| .USA.${AND}.Greece. | Greece | False |
| .USA.${AND}.Greece. | Greece USA | True |
NOT Operation
The RELookup supports negative logic (NOT) for expressions. This is accomplished by prefixing the expressions with “${NOT}”. In the following example, the regular expression “.USA.” only returns true if the text does not contain the word “USA”. Note that multiple “${NOT}”(s) can be chained together with “${AND}”(s) (see table below).
| ${NOT}.USA. | USA and Greece | False |
| ${NOT}.USA. | USA | False |
| ${NOT}.USA. | Greece | True |
| ${NOT}.USA. | Greece USA | False |
| .Greece.${AND}${NOT}.USA. ${AND}${NOT}.Turkey. | Greece Turkey | False |
| .Greece.${AND}${NOT}.USA. ${AND}${NOT}.Turkey. | Greece Africa | True |
USAGE
ReLookup<FaultError> lookup = new ReLookup<FaultError>();
assertTrue(lookup instanceof Map);
lookup.put("(001)*.*Green.*${AND}${NOT}.*Blue.*", new FaultError("0001","ERROR"));
lookup.put("(002)*.*Green.*${AND}.*Blue.*", new FaultError("0002","GB"));
lookup.put("(003)*.*Blue.*", new FaultError("0003","BLUE"));
assertEquals(lookup.get("Green").getCode(), "0001");
assertEquals(lookup.get("Blue Green").getCode(), "0002");
assertEquals(lookup.get("Blue with Live of pure").getCode(), "0003");
Fault Pattern
See package nyla.solutions.core.exception.fault
Use the FaultsHtmlTextDecorator to get HTML summary of the FaultException or just objects the implement the nyla.solutions.core.exception.fault.Fault interface.
Collection<Fault> faults = new ArrayList<Fault>();
faults.add(faultException);
FaultsHtmlTextDecorator decorator = new FaultsHtmlTextDecorator(faults);
String faultsSummaryHtml = decorator.getText();
You can override the HTML template by putting the following files first in the classpath:
templates/FaultsHtmlTextDecorator_ROW.txt
templates/FaultsHtmlTextDecorator.txt
You can also override the default template classpath locator from "template" by setting the following config property.
nyla.solutions.core.util.Text.TEMPLATE_CLASSPATH_ROOT=myclassPathRoot
Example
nyla.solutions.core.util.Text.TEMPLATE_CLASSPATH_ROOT=/com/company/templates
Example HTML output:
<html> <body>
<div>
<table>
<tr>
<thead>
<td>code</td>
<td>message</td>
<td>category</td>
<td>module</td>
<td>errorStackTrace</td>
</thead>
</tr>
<tr> <td>001</td>
<td>test_message</td>
<td></td>
<td></td>
<td>nyla.solutions.core.exception.fault.FaultException: test_message
at nyla.solutions.core.exception.fault.FaultsHtmlDecoratorTest.testGetText(FaultsHtmlDecoratorTest.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
</td>
</tr>
</table>
</div>
</body>
</html>
MappedTextFormatDecorator Pattern
The class nyla.solutions.core.patterns.decorator.MappedTextFormatDecorator
can be used to generator dynamic based
on template
text based on the Textable/TextDecorator
MappedTextFormatDecorator subject = .new MappedTextFormatDecorator();
String url = "http://localhost:8080/template/MappedTextFormatDecoratorTest.txt";
Map<String, Textable> map = new HashMap<>();
map.put("fn", new StringText(new FirstNameCreator().create()));
map.put("ln", new StringText(new LastNameCreator().create()));
subject.setTemplateUrl(url);
String text = subject.getText();
The following is an example template
at a URL:
Hello ${fn} ${ln}
You also set the template without using a
URL.
subject.setTemplate("I love ${fn} ${ln}");
Java Bean Generator Creator
See package nyla.solutions.core.patterns.creational.generator
JavaBeanGeneratorCreator can be used to auto generate properties for any object.
The following will auto generate random data for the "email" property.
JavaBeanGeneratorCreator<UserProfile> creator = new JavaBeanGeneratorCreator<UserProfile>(UserProfile.class);
creator.randomizeProperty("email");
UserProfile userProfile = creator.create();
assertNotNull(userProfile);
assertTrue(userProfile.getEmail() != null && userProfile.getEmail().length() > 0 );
The following auto generate all supported properties in the provided object.
JavaBeanGeneratorCreator<UserProfile> creator = new JavaBeanGeneratorCreator<UserProfile>(UserProfile.class);
creator.randomizeAll();
JavaBeanGeneratorCreator<UserProfile> creator = new JavaBeanGeneratorCreator<UserProfile>(UserProfile.class);
creator.randomizeAll();
assertTrue(creator.getRandomizeProperties().contains("firstName"));
assertTrue(creator.create().getEmail().length() > 0);
The following uses a proxy to generate new objects. The proxy is copied with only the indicated properties auto generated with each create method.
UserProfile protoype = new UserProfile();
protoype.setFirstName("Imani");
protoype.setLastName("Green");
JavaBeanGeneratorCreator<UserProfile> creator = new JavaBeanGeneratorCreator<UserProfile>(protoype);
creator.randomizeProperty("email");
UserProfile u1 = creator.create();
assertEquals(u1.getFirstName(),protoype.getFirstName());
assertEquals(u1.getLastName(),protoype.getLastName());
assertNotNull(u1.getEmail());
assertTrue(u1.getEmail().length() > 0);
If you have a fairly complex object with multiple nested objects,
you can use the generateNestedAll in addition to the randomizeAll to
create random data for nested objects.
JavaBeanGeneratorCreator<ComplexObject> creator = new
JavaBeanGeneratorCreator<ComplexObject>(ComplexObject.class)
.randomizeAll()
.generateNestedAll();
ComplexObject complexObject = creator.create();
JavaBeanGenerator will also generator reasonably valid
values for fields such as "firstName", "lastName",
"phone", "mobile", "fax" and "email" based on the
provided objects properties names.
For example, the following code
UserProfile userProfile = new JavaBeanGeneratorCreator<UserProfile>(UserProfile.class)
.randomizeAll().create();
System.out.println(userProfile);
Results in the following output. Notice,
the random generated values for first, last name,
email and phone.
nyla.solutions.core.security.user.
data.UserProfile[email=wslom@dutvs.ubvu,
loginID=467230864,
firstName=Walter,lastName=Neal,
title=20200524224944759144752447,
phone=555-555-5708,
...
The following is a more complex customization. The sample generate credit card
transaction data.
new JavaBeanGeneratorCreator(Transaction.class)
.generateNestedAll()
.randomizeAll()
.creatorForProperty("name_on_card", new FullNameCreator())
.creatorForProperty("expiry_year", () -> digits.generateShort(minYear,maxYear))
.creatorForProperty("expiry_month", () -> digits.generateShort(minMonth,maxMonth))
.creatorForProperty("brand", PickRandomTextCreator.options("Amex",
"Discover","Wells Fargo","Citigroup","Chase","Barclays",
"MasterCard","PNC Bank","Visa","Navy Federal Credit Union"))
.creatorForProperty("card_type", PickRandomTextCreator.options("Amex",
"Rewards","Cashback","Travel","Business","Corporate"))
.creatorForProperty("description",PickRandomTextCreator.options("issued by a financial company",
" minimum payment each period","Summary of account activity","basic terms that you may come across when using your credit card."));
JSON Generation
The class JsonGeneratorCreator is creational
implementation to generator example JSON
output similar to the JavaBeanGenerator.
See nyla.solutions.core.patterns.creational.generator.json.JsonGeneratorCreator
It will also generator reasonably valid
values for fields such as "firstName", "lastName",
"phone", "mobile", "fax" and "email" based on the
provided type properties names.
The supported data types are base on the JsonPropertyType
object (ex: String, Integer, Number and Boolean).
Example Usage using the Properties object.
Properties properties = new Properties();
properties.setProperty("firstName","String");
properties.setProperty("lastName","String");
properties.setProperty("updateDate","String");
properties.setProperty("cost","Number");
properties.setProperty("count","Integer");
JsonGeneratorCreator c =
new JsonGeneratorCreator(DateTimeFormatter.ISO_DATE,
properties);
String json = c.create();
Example JSON output
{"firstName":"Keith","lastName":"Jackson","updateDate":"2020-07-04","cost":0.011549557733887772,"count":119629238}
You can also use a JsonSchemaBluePrint
object to create the JsonGeneratorCreator.
sJsonSchemaBluePrint jsonSchemaBluePrint = new JsonSchemaBluePrint(DateTimeFormatter.ISO_DATE);
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("isTrue", JsonPropertyType.Boolean));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("cost", JsonPropertyType.Number));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("count", JsonPropertyType.Integer));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("name", JsonPropertyType.String));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("date", JsonPropertyType.String));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("firstName", JsonPropertyType.String));
jsonSchemaBluePrint.addPropertySchema(new JsonPropertySchema("lastName", JsonPropertyType.String));
JsonGeneratorCreator c =
new JsonGeneratorCreator(jsonSchemaBluePrint);
String json = c.create();
Cache Farm
See package nyla.solutions.core.patterns.cache
Cache Farm is a simple singleton implementation of cached key/value pairs.
Cache<Object,Object> cacheFarm = CacheFarm.getCache();
cacheFarm.put("key",myObject);
CSV
See package nyla.solutions.core.io.csv
The following is used to parse CSV lines nyla.solutions.core.io.csv.CsvReader
List<String> results = CsvReader.parse("1,2");
assertNotNull(results);
assertEquals("1", results.get(0));
assertEquals("2", results.get(1));
results = CsvReader.parse("\"1,2\"");
assertEquals("1,2", results.get(0));
results = CsvReader.parse("0,\"1,2\"");
assertEquals("0", results.get(0));
assertEquals("1,2", results.get(1));
results = CsvReader.parse("0,\"1,2\",\"Greg's\"");
assertEquals("0", results.get(0));
assertEquals("1,2", results.get(1));
assertEquals("Greg's", results.get(2));
results = CsvReader.parse("0,\"1,2\",\"Greg's\",\"last");
assertEquals("last", results.get(3));
results = CsvReader.parse("\"0\",\"The \"\"GOOD\"\"\",2");
assertEquals("0", results.get(0));
assertEquals("The \"GOOD\"", results.get(1));
assertEquals("2", results.get(2));
LDAP
See package nyla.solutions.core.ds
The object nyla.solutions.core.ds.LDAP provides a simple wrapper for LDAP authentication and searching.
String adminDN = "uid=admin,ou=system";
char[] adminPwd ="secret".toCharArray();
String user = "imani";
char[] pwd = "password".toCharArray();
try(LDAP ldap = new LDAP("ldap://localhost", adminDN, adminPwd))
{
Principal principal = ldap.authenicate(user,pwd,"ou=system","uid","memberOf","CN",100);
assertEquals(user,principal.getName());
}
LDAPS (or LDAP over SSL/TLS support)
Set the following configuration properties in order to enable secure LDAP communication.
| LDAP_USE_SSL_CONFIG_FACTORY | (true or false) Boolean value to determine if LDAPS is used with the following configurations properties |
| "LDAP_SSL_KEYSTORE" | The SSL KEYSTORE file path location |
| "LDAP_SSL_TRUSTSTORE" | The SSL KEYSTORE file path location |
| "LDAP_SSL_KEYSTORE_PASSWORD" | The password for the key store |
| "LDAP_SSL_TRUSTSTORE_PASSSWORD" | The password for the trust store |
Security
See package nyla.solutions.core.security.data
Access Control List
Principal caller = null;
Principal principal = null;
SecurityAcl securityAcl = new SecurityAcl();
principal = new SecurityGroup("group");
caller = new SecurityClient("admin");
securityAcl.addEntry(caller,principal, false,"CLUSTER");
assertTrue(securityAcl.checkPermission(principal, "CLUSTER"));
securityAcl.addEntry(caller,principal, true,"CLUSTER");
assertFalse(securityAcl.checkPermission(principal, "CLUSTER"));
Graphics
See package nyla.solutions.core.media
Capture screen shots
Graphics graphics = new Graphics();
graphics.printScreen(0, 0, 1000, 800, "png", new File("runtime/tmp/output/screenshot.png"));
Rotate images
Example rotate 45 degrees
Graphics graphics = new Graphics();
graphics.rotateImage(Paths.get("test-in.png").toFile(),Paths.get("test-out.png"),toFile(),Graphics.Format.PNG,45);
Expirations
See package nyla.solutions.core.data.expiration
ExpiringKeyValueLookup
The ExpiringKeyValueLookup class can be used for simple hash based look ups with expiring content.
This is a good class to use for implementing caching.
Example Code
ExpiringKeyValueLookup<String,String> bag = ExpiringKeyValueLookup.withExpirationMS(1000);
assertNotNull(bag);
bag.putEntry("1","1");
assertEquals("1",bag.getValue("1"));
Thread.sleep(1001);
assertNull(bag.getValue("1"));
ExpiringItem
The ExpiringItem class can be used for a single value with expiring content.
Example Code
ExpiringItem<String> e = new ExpiringItem<>("hello",
LocalDateTime.now().plusSeconds(1));
assertEquals("hello",e.value());
Thread.sleep(1050);
assertNull(e.value());
Performance
var perfTest = new PerformanceCheck(benchMark,statsCapacity);
try(producer)
{
perfTest.perfCheck(()->{
producer.send(new ProducerRecord<String, String>("my-topic", key,value));
});
}
nyla.solutions.core.operations.performance.stats.ThroughputStatistics
This calculating throughput statistics
ThroughputStatistics subject = new ThroughputStatistics();
long expected = 1000;
LocalDateTime now = LocalDateTime.now();
subject.increment(expected);
assertEquals(Double.valueOf(expected),subject.throughputPerSecond(now,now.plusSeconds(1)));
Generator
nyla.solutions.core.patterns.creational.generator
GenerateTextWithPropertiesCreator can replace common placeholder values with randomly
generated text.
Support placeholders
- {id}
- ${email}
- ${firstName}
- ${lastName}
- ${name}
- ${fullName}
- ${phone}
- ${mobile}
- ${fax}
- ${date}
- ${intRange}
String template = "Hello ${id} ${email} ${firstName} ${lastName} ${name} ${fullName}, "+
"your phone is ${phone}, your cell is ${mobile} your fax is ${fax} "+
"generated on ${date}";
GenerateTextWithPropertiesCreator subject = new GenerateTextWithPropertiesCreator(template);
String actual = subject.getText();
Business Rule Engine (BRE)
package nyla.solutions.core.patterns.expression.bre
The business rules engine is a software system that executes one or more function rules in at runtime.
The BusinessRuleEngine supports chaining Function calls to be executed based on a logical rule name.
BusinessRuleEngine<Integer,Boolean> abnormalVitalBre = BusinessRuleEngine
.builder()
.rule("heartRate",
new OrExpression<Integer>(ComparableExpression.lessThan(55),
ComparableExpression.greaterThan(105)))
.rule("bodyTemperature",new OrExpression<Integer>(
ComparableExpression.lessThan(95),
ComparableExpression.greaterThan(103)))
.rule( "respirationRate",new OrExpression<Integer>(
ComparableExpression.lessThan(12),
ComparableExpression.greaterThan(16)))
.rule("bloodPressureDiastolic", ComparableExpression.lessThan(80))
.rule("bloodPressureSystolic", ComparableExpression.greaterThan(130))
.build();
assertEquals(true,abnormalVitalBre.applyForRule("bodyTemperature",200));
assertEquals(false,abnormalVitalBre.applyForRule("bodyTemperature",98));
Building
Set your ossrUsername and ossrhPassword in the ~/.gradle
ossrhUsername=userName
ossrhPassword=<password>
- Change directory to the root directory
- $gradle install
FAQ
Add the following to gradle.properties
signing.keyId=KEYID
#ossrh
signing.password=PASSWORD
signing.secretKeyRingFile=<HOME>/secring.gpg
Subject Registry
The nyla.solutions.core.patterns.observer.SubjectRegistry object is an object/mapping of multiple topics and observers.
String subjectName = "hello";
subject = new SubjectRegistry();
subject.register(subjectName,observer);
subject.notify(subjectName,userProfile);
subject.notifyAll(userProfile);