Initial Commit

This commit is contained in:
Isaac Parenteau
2019-07-20 12:39:03 -05:00
commit 79529ecc40
66 changed files with 6549 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
package net.locusworks.common.utils;
public class Checks {
public static void checkArguments(boolean expression, String error) {
checkArguments(expression, "%s", error);
}
public static void checkArguments(boolean expression, String errorFmt, Object... args) {
if (!expression) throw new IllegalArgumentException(String.format(errorFmt, args));
}
public static void checkState(boolean expression, String error) {
checkState(expression, "%s", error);
}
public static void checkState(boolean expression, String errorFmt, Object... args) {
if (!expression) throw new IllegalStateException(String.format(errorFmt, args));
}
public static void checkNotNull(Object item, String error) {
if (item == null) throw new IllegalAccessError("Provided item is null");
}
}

View File

@@ -0,0 +1,19 @@
package net.locusworks.common.utils;
/**
* Class to hold final static constant values used across the system
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class Constants {
public static final short TRUE = (short)1;
public static final short FALSE = (short)0;
public static final short EXIT_SUCCESS = (short)0;
public static final short EXIT_FAIL = (short)1;
public static final String LOG4J_CONFIG_PROPERTY = "log4j.configurationFile";
public static final String JUNIT_TEST_CHECK = "junit.test";
}

View File

@@ -0,0 +1,50 @@
package net.locusworks.common.utils;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Base64;
import net.locusworks.common.Charsets;
public class DataOutputStreamHelper extends DataOutputStream implements AutoCloseable{
public DataOutputStreamHelper() {
this(new ByteArrayOutputStream());
}
public DataOutputStreamHelper(OutputStream out) {
super(out);
}
public byte[] toByteArray() {
if (super.out == null) {
return new byte[0];
}
if (super.out instanceof ByteArrayOutputStream) {
return ((ByteArrayOutputStream)super.out).toByteArray();
}
return super.out.toString().getBytes(Charsets.UTF_8);
}
public String base64Encoded() {
return Base64.getEncoder().encodeToString(this.toByteArray());
}
@Override
public String toString() {
return new String(this.toByteArray(), Charsets.UTF_8);
}
@Override
public void close() throws IOException {
if (super.out != null) {
try {
super.out.close();
super.out = null;
} catch (Exception ex) {}
}
}
}

View File

@@ -0,0 +1,107 @@
package net.locusworks.common.utils;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
/**
* Class to deseralize json data into a Date object back into a class that specifies this deserializer <br>
* For example the below code:
* <pre>
* {@code @JsonDeserialize(using=DateTimeStampDeserializer.class)
* private Date purgeEndDate;}
* </pre>
* Will specify to use this deserializer class when a json field {@code purgeEndDate} is encountered in the json
* string and will try to convert the string into a date object and inject the value back into the class
* @author Isaac Parenteau
* @version 1.0
* @date 02/15/2018
* @see com.fasterxml.jackson.databind.annotation.JsonDeserialize
*/
public class DateTimeStampDeserializer extends JsonDeserializer<Date> {
private static final String DEFAULT = "MM/dd/yyyy";
private static final String EXPANDED = "MM/dd/yyyy HH:mm:ss z";
private static final String EXPANDED_WITH_TIMEZONE = "MMM d, yyyy HH:mm:ss z";
private static final String EXPANDED_WITH_AM_PM = "MMM d, yyyy h:mm:ss a";
private static final String[] formats = new String[] {
DEFAULT,
EXPANDED,
EXPANDED_WITH_TIMEZONE,
EXPANDED_WITH_AM_PM,
};
private static final Integer[] styles = new Integer[] {
SimpleDateFormat.LONG,
SimpleDateFormat.FULL,
SimpleDateFormat.MEDIUM,
SimpleDateFormat.SHORT
};
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String value = p.getText();
Date date = null;
//First try to see if the value can be parsed into a long
try {
date = new Date(Long.parseLong(value));
return date;
} catch (Exception ex) { }
//Next iterate over the built in styles to see if it can be converted
for (Integer style: styles) {
date = formatDate(style, value);
if (date != null) {
return date;
}
}
//Lastly iterate over the custom styles specified in format to see if it can be converted
for (String fmt : formats) {
date = formatDate(fmt, value);
if (date != null) {
return date;
}
}
//Return null if date format can't be converted
return null;
}
/**
* Convert a string value to a date object
* @param format The format to use in reference to the source
* @param source the source to convert
* @return Date object if the conversion was success; null otherwise
*/
private static Date formatDate(String format, String source) {
try {
return new SimpleDateFormat(format).parse(source);
} catch (Exception ex) {
return null;
}
}
/**
* Convert a string value to a date object using SimpleDateFormats
* built in styles
* @param style The style to use
* @param source the source to convert
* @return Date object if the conversion was success; null otherwise
*/
private static Date formatDate(Integer style, String source) {
try {
return SimpleDateFormat.getDateInstance(style).parse(source);
} catch (Exception ex) {
return null;
}
}
}

View File

@@ -0,0 +1,46 @@
package net.locusworks.common.utils;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Class to serialize a date object into a json string value <br>
* This serializer will convert date objects to their timestamp representation <br>
* For example the below code:
* <pre>
* {@code @JsonSerialize(using=DateTimeStampSerializer.class)
* private Date purgeEndDate;
* }
* </pre>
* Will specify to use this serializer class when the {@code purgeEndDate} is encountered when converting to json
* and will try to convert the date object to its timestamp equivalent
* @author Isaac Parenteau
* @date 02/15/2018
* @version 1.0
* @see com.fasterxml.jackson.databind.annotation.JsonSerialize
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer
*/
public class DateTimeStampSerializer extends StdSerializer<Date> {
/**
*
*/
private static final long serialVersionUID = -4753139740916300831L;
public DateTimeStampSerializer() {
this(null);
}
public DateTimeStampSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize(Date date, JsonGenerator generator, SerializerProvider provider) throws IOException {
generator.writeNumber(date.getTime());
}
}

View File

@@ -0,0 +1,202 @@
package net.locusworks.common.utils;
import static net.locusworks.common.Charsets.UTF_8;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.NoSuchElementException;
import net.locusworks.common.interfaces.AutoCloseableIterator;
/**
* Class to read in a file that can be used in the try-with-resource block
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class FileReader implements AutoCloseableIterator<FileReader.LineInfo>, Iterable<FileReader.LineInfo> {
private BufferedReader reader;
private LineInfo info;
private Integer lineNumber;
/**
* Constructor
* @param fileName Name of the file to read
*/
public FileReader(String fileName) {
init(fileName);
}
/**
* Constructor
* @param file File to read
*/
public FileReader(File file) {
init(file);
}
/**
* Constructor
* @param reader Buffered reader to read data from
*/
public FileReader(BufferedReader reader) {
init(reader);
}
/**
* Initialization helper
* @param fileName Name of the file to load
* This will look into the resources directory if it cannot
* find the file directly.
*/
private void init(String fileName) {
//check to see if the file exists
File f = new File(fileName);
if (f.exists()) {
init(f); //If it does. load through the file initializer
return;
}
//Check to see if the file is in the resources directory
InputStream is = this.getClass().getResourceAsStream(fileName);
if (is == null) {
is = this.getClass().getClassLoader().getResourceAsStream(fileName);
}
//If it cant be found, throw a runtime exception
if (is == null) {
throw new IllegalArgumentException("Unable to find resource with name of" + fileName);
}
//Call the buffered reader initializer once the file is found
init(new BufferedReader(new InputStreamReader(is, UTF_8)));
}
/**
* Initializer helper to load file
* @param file File to load
*/
private void init(File file) {
if (file == null) throw new IllegalArgumentException("File cannot be null");
if (!file.exists()) throw new IllegalArgumentException("File " + file + " does not exist");
if (!file.isFile()) throw new IllegalArgumentException("File " + file + " is not a file");
try {
init(new BufferedReader(new InputStreamReader(new FileInputStream(file), UTF_8)));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
/**
* Initializer helper for buffered reader
* This is ultimately where all initializers end as a buffered reader
* @param reader buffered reader to load
*/
private void init(BufferedReader reader) {
this.reader = reader;
this.lineNumber = 0;
}
@Override
public boolean hasNext() {
try {
String line = this.reader.readLine();
if (line == null) {
this.close();
this.info = null;
return false;
}
this.lineNumber++;
this.info = new LineInfo(this.lineNumber, line);
return true;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@Override
public LineInfo next() {
if (this.info == null) {
throw new NoSuchElementException("Call to next was initiated but there are no more elements to read");
}
return this.info;
}
@Override
public Iterator<LineInfo> iterator() {
return this;
}
@Override
public void close() {
if (this.reader != null) {
try {
this.reader.close();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
public static class LineInfo {
private Integer lineNumber;
private Integer lineLength;
private String line;
/**
* @param lineNumber the current line number in the file
* @param line the line information from the file
*/
public LineInfo(Integer lineNumber, String line) {
this.lineNumber = lineNumber;
this.line = line;
this.lineLength = line.length();
}
/**
* @return the lineNumber
*/
public Integer getLineNumber() {
return lineNumber;
}
/**
* @param lineNumber the lineNumber to set
*/
public void setLineNumber(Integer lineNumber) {
this.lineNumber = lineNumber;
}
/**
* @return the lineLength
*/
public Integer getLineLength() {
return lineLength;
}
/**
* @param lineLength the lineLength to set
*/
public void setLineLength(Integer lineLength) {
this.lineLength = lineLength;
}
/**
* @return the line
*/
public String getLine() {
return line;
}
/**
* @param line the line to set
*/
public void setLine(String line) {
this.line = line;
}
}
}

View File

@@ -0,0 +1,179 @@
package net.locusworks.common.utils;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* Wrapper class that leverages java's MessageDigest to hash files
* @author Isaac Parenteau
*
*/
public class HashUtils {
private static final Charset UTF_8 = StandardCharsets.UTF_8;
/**
* Used to build output as Hex
*/
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Used to build output as Hex
*/
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* Size of the streaming buffer
*/
public static final Integer STREAM_BUFFER_LENGTH = 1024;
/**
* Hash a string literal
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data String to hash
* @return hash value of the string literal
*/
public static String hash(String hashType, String data) {
return hash(hashType, data, true);
}
/**
* Hash a string literal
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data String to hash
* @param toLower True to output the hash in lower case. False to output in upper case
* @return hash value of the string literal
*/
public static String hash(String hashType, String data, boolean toLower) {
byte[] stringData = data.getBytes(UTF_8);
return hash(hashType, stringData, toLower);
}
/**
* Hash a file
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data File to hash
* @return hash value of the file
*/
public static String hash(String hashType, File data) {
return hash(hashType, data, true);
}
/**
* Hash a file
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data File to hash
* @param toLower True to output the hash in lower case. False to output in upper case
* @return hash value of the file
*/
public static String hash(String hashType, File data, boolean toLower) {
InputStream stream;
try {
stream = new FileInputStream(data);
} catch (IOException ex) {
throw new IllegalArgumentException(ex.getMessage());
}
return hash(stream, hashType, toLower);
}
/**
* Hash a byte array
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data data to hash
* @return hash value of the data
*/
public static String hash(String hashType, byte[] data) {
return hash(hashType, data, true);
}
/**
* Hash a byte array
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param data data to hash
* @param toLower True to output the hash in lower case. False to output in upper case
* @return hash value of the data
*/
public static String hash(String hashType, byte[] data, boolean toLower) {
return hash(new BufferedInputStream(new ByteArrayInputStream(data)), hashType, toLower);
}
/**
* Hash an input stream
* @param stream Stream with the data to hash
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @return Hash value of the input stream
*/
public static String hash(InputStream stream, String hashType) {
return hash(stream, hashType, true);
}
/**
* Hash an input stream
* @param stream Stream with the data to hash
* @param hashType Hash types supported by MessageDigest (i.e MD5, SHA-1, SHA-512)
* @param toLower True to output the hash in lower case. False to output in upper case
* @return Hash value of the input stream
*/
public static String hash(InputStream stream, String hashType, boolean toLower) {
MessageDigest digest = null;
try(InputStream is = stream) {
digest = MessageDigest.getInstance(hashType);
byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = is.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
digest.update(buffer, 0, read);
read = is.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return encodeHexString(digest.digest(), toLower);
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage());
}
}
/**
* Encode the hash data back to a string
* @param data Data to encode
* @param toLower output to lower case
* @return
*/
private static String encodeHexString(byte[] data, boolean toLower) {
return new String(encodeHex(data, toLower));
}
/**
* Encode the hash data to a character array
* @param data Data to encode
* @param toLower output to lower case
* @return
*/
private static char[] encodeHex(byte[] data, boolean toLower) {
return encodeHex(data, toLower ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* Encode the hex to a character array
* @param data Data to encode
* @param toDigits digits to use
* @return
*/
private static char[] encodeHex(byte[] data, char[] toDigits) {
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return out;
}
}

View File

@@ -0,0 +1,79 @@
package net.locusworks.common.utils;
import java.security.SecureRandom;
import java.util.Objects;
import java.util.Random;
import static net.locusworks.common.Charsets.UTF_8;
public class RandomString {
public static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
public static final String UPPER = LOWER.toUpperCase();
public static final String DIGITS = "0123456789";
public static final String ALPHA_NUMERIC = LOWER + UPPER + DIGITS;
private Random random;
private char[] symbols;
private int length;
private static RandomString instance;
private RandomString(Integer length) {
this(length, new SecureRandom());
}
private RandomString(Integer length, Random random) {
this(length, random, ALPHA_NUMERIC);
}
private RandomString(Integer length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException("Length has to be greater than 1");
if (symbols.length() < 2) throw new IllegalArgumentException("Symbols need to be greater than 2");
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
}
private synchronized final void setRandom(Random random) {
this.random = random;
}
private synchronized final void setLength(int length) {
this.length = length;
}
public String nextString() {
char[] buffer = new char[length];
for (int index = 0; index < buffer.length; index++) {
buffer[index] = symbols[random.nextInt(symbols.length)];
}
return new String(buffer);
}
public static String getString(Integer length) {
if (instance == null) {
instance = new RandomString(length);
}
instance.setLength(length);
return instance.nextString();
}
public static String getString(Integer length, Random random) {
if (instance == null) {
instance = new RandomString(length);
}
instance.setLength(length);
instance.setRandom(random);
return instance.nextString();
}
public static byte[] getBytes(Integer length) {
return getString(length).getBytes(UTF_8);
}
public static byte[] getBytes(Integer length, Random random) {
return getString(length, random).getBytes(UTF_8);
}
}

View File

@@ -0,0 +1,130 @@
package net.locusworks.common.utils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static net.locusworks.common.utils.Checks.checkArguments;
import static net.locusworks.common.utils.Checks.checkNotNull;
public class Splitter {
private String splitSeq;
private boolean omitEmptyStrings = false;
private int partition;
private int limit;
private static Splitter splitter;
private Splitter(String seq) {
this.splitSeq = seq;
}
private Splitter(int partition) {
this.partition = partition;
}
public Splitter omitEmptyStrings() {
this.omitEmptyStrings = true;
return this;
}
public Splitter withLimit(int limit) {
this.limit = limit;
return this;
}
public MapSplitter withKeyValueSeparator(String separator) {
checkArguments(!Utils.isEmptyString(separator), "Key value separator cannot be empty or null");
return new MapSplitter(this, separator);
}
public String[] splitToArray(String sentence) {
List<String> list = split(sentence);
return list.toArray(new String[list.size()]);
}
public List<String> split(String sentence) {
checkArguments(!Utils.isEmptyString(sentence), "provided value is null or empty");
List<String> list = new ArrayList<>();
if (!Utils.isEmptyString(splitSeq))
populateForTrimmer(sentence, list);
else
populateForFixedWidth(sentence, list);
return limit > 0 ? list.subList(0, limit) : list;
}
private void populateForFixedWidth(String sentence, List<String> list) {
int strLength = sentence.length();
for (int i = 0; i < strLength; i += partition) {
list.add(sentence.substring(i, Math.min(strLength, i + partition)));
}
}
private void populateForTrimmer(String sentence, List<String> list) {
for (String s : sentence.split(splitSeq)) {
if (s == null || (omitEmptyStrings && s.trim().isEmpty())) continue;
list.add(s.trim());
}
}
public static Splitter fixedLengthSplit(int partition) {
checkArguments(partition > 0, "Partition has to be greater than 0");
splitter = new Splitter(partition);
return splitter;
}
public static Splitter on(String split) {
checkNotNull(split, "Split value provided was null");
splitter = new Splitter(split);
return splitter;
}
public static Splitter onNewLine() {
return on("\\r?\\n");
}
public static Splitter onSpace() {
return on(" ");
}
public static class MapSplitter {
private Splitter splitter;
private String separator;
private boolean skipInvalid = false;
private MapSplitter(Splitter splitter, String separator) {
checkNotNull(splitter, "Splitter cannot be null");
checkArguments(!Utils.isEmptyString(separator), "Key value separator cannot be empty or null");
this.splitter = splitter;
this.separator = separator;
}
public MapSplitter skipInvalidKeyValues() {
this.skipInvalid = true;
return this;
}
public Map<String, String> split(String sentence) {
checkArguments(!Utils.isEmptyString(sentence), "provided value is null or empty");
Map<String, String> map = new LinkedHashMap<>();
for (String s : splitter.split(sentence)) {
String[] keyValue = s.split(separator);
try {
checkArguments(keyValue.length == 2, "invalid length found for key value mapping");
} catch (IllegalArgumentException ex) {
if (!skipInvalid) throw ex;
continue;
}
map.put(keyValue[0], keyValue[1]);
}
return map;
}
}
}

View File

@@ -0,0 +1,66 @@
package net.locusworks.common.utils;
import java.util.Arrays;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Utility class to make iterators streamable
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class StreamUtils {
/**
* Convert a iterator to a stream
* @param iterator the iterator to convert
* @param <T> the class type
* @return stream of the iterator
*/
public static <T> Stream<T> asStream(Iterator<T> iterator) {
return asStream(iterator, false);
}
public static <T> Stream<T> asStream(Iterable<T> iterable) {
return asStream(iterable, false);
}
/**
* Converts an array to a stream
* @param items the items to convert
* @param <T> the class type
* @return stream of the array
*/
public static <T> Stream<T> asStream(T[] items) {
return asStream(Arrays.asList(items).iterator(), false);
}
/**
* Converts an array to a stream
* @param items the items to convert
* @param parallel make the stream parallel if set to true
* @param <T> the class type
* @return stream of the array
*/
public static <T> Stream<T> asStream(T[] items, boolean parallel) {
return asStream(Arrays.asList(items).iterator(), parallel);
}
public static <T> Stream<T> asStream(Iterable<T> iterable, boolean parallel) {
return StreamSupport.stream(iterable.spliterator(), parallel);
}
/**
* Convert an iterator to a stream
* @param iterator iterator to convert
* @param parallel make the stream parallel if set to true.
* @param <T> the class type
* @return stream of the iterator
*/
public static <T> Stream<T> asStream(Iterator<T> iterator, boolean parallel) {
Iterable<T> iterable = () -> iterator;
return StreamSupport.stream(iterable.spliterator(), parallel);
}
}

View File

@@ -0,0 +1,41 @@
package net.locusworks.common.utils;
/***
* Success class to return data back to the client
* @author Isaac Parenteau
* @version 1.0.0
* @date 02/15/2018
*/
public class Success {
private boolean success = true;
private Object body;
protected Success() {
this(true, true);
}
protected Success(boolean success) {
this(success, success);
}
public Success(boolean success, Object body) {
this.success = success;
this.body = body;
}
public Object getBody() {
return body;
}
public boolean getSuccess() {
return success;
}
public static Success success() {
return new Success();
}
public static Success fail() {
return new Success(false);
}
}

File diff suppressed because it is too large Load Diff