jpropel

Multi-functional, cross-platform, well documented framework cutting boilerplate and speeding up your software development process

33
3
Java

Description

Boilerplate busting framework with features found in many modern programming
environments, such as LINQ, reified collections and numerous one-liner
type utility methods, e.g. loading a file into memory.

Open source (LGPL), cross platform, cross culture, compatible with legacy
environments (e.g. JDK 1.5) and single JAR deployment.

News

Forked a much leaner version at -> https://github.com/nicholas22/jpropel-light
Contains only LINQ, reified generic collections and utilities.
Documented these features in the front page of that project.

Highly recommended if you don’t want extra dependencies in your libraries.

Change logs

CHANGELOG 1.0.8

  • Remove runtime dependency of lombok-pg
  • Library is now compile-time only dependent on lombok (the parent project)
  • Made it clearer that license is LGPL
  • Added Nullable check methods
  • Added Linq.toString for collections
  • Added ReflectionUtils.toString for POJOs
  • FileUtils.moveFile returns boolean
  • Linq toList optimisation (check instanceof List)
  • ExceptionUtils unchecked throw (as sneakyThrows replacement)

CHANGELOG 1.0.7

  • StringUtils faster replace with StringBuilder
  • FileUtils methods for checking if a file exists
  • ConversionUtils support for Period and DateTime
  • XmlUtils faster compaction
  • ArrayUtils copy helper method
  • Nullable method for NPE check
  • StackTraceLogger remove trailing CRLF chars

CHANGELOG 1.0.6

  • ReifiedArrayList fix (thanks to Redudent!)
  • syntax in readme

CHANGELOG 1.0.5

  • Bugfix for ReflectionUtils getSetters and getProperties
  • Block iterator for per-line file reading

CHANGELOG 1.0.4

  • Bugfixing
  • Minor improvements

CHANGELOG 1.0.3

  • Upgraded dependency lombok-pg to v0.11.0
  • Upgraded dependency slf4j-api to v1.6.4
  • ThreadUtils methods for sleep, busy-spin, yield waiting
  • Added methods getSetter and getGetter in ReflectionUtils
  • Added FileUtils directory methods accepting File as arg
  • NPE cleanup, using Validate.NotNull in most Util classes
  • Bugfixing Linq (type constraints)
  • Bugfixing in ArrayUtils (reverse method)
  • Breaking changes:
    • Moved some ArrayUtils methods to Linq for consistency
    • Projections organised as Arrays, Objects, Files, etc.
    • Removed duplicates

CHANGELOG 1.0.2

  • Bugfixing validators and logger

CHANGELOG 1.0.1

  • Added EnvironmentUtils utility class, allows for altering JVM env. vars at run-time
  • Added Stopwatch.restart() convenience method
  • Added Iterable validator (IterablePropertyMetadata)
  • Added URL validator (URLPropertyMetadata)
  • Added a few commonly used predicates (propel.core.functional.predicates.*)
  • StackTraceLogger now has configurable level, showing minimal, abbreviated or full trace
  • Fixed inaccurate comments in NumericUtils, StringUtils, Linq, etc.
  • Linq unzip() and partition() methods added. Bug-fixing (ofType, orderByThenBy, skip)
  • Using lombok-pg 0.10.8-SNAPSHOT dependency
  • Using slf4j-api 1.6.4 dependency
  • Included Eclipse project in sources JAR

CHANGELOG 1.0.0

  • LongHashMap now has very fast lookup performance and smaller memory footprint
  • Added ReflectionUtils.proxy() overload allowing you to “seal” certain class methods
    (via proxying) and as such guaranteeing immutability for things like collections.
  • Using these two features together (i.e. a long->T map and immutability), you can
    create a hash map that is ~500% faster than ConcurrentHashMap (during lookups).
    This is due to absence of locking. See ImmutableUtils.toReadOnly().
  • Improved InitGuard interface / comments.
  • Extracted interface for MapMultimaps
  • Removed SharedLongHashMap implementation.

CHANGELOG 0.9.9

  • Support for primitive (long-based) collections (buffers, maps)
  • Generic Frozen object container, can only be set once
  • StringUtils.replace() bugfix
  • Validation error message improvement when min & max length are equal
  • Replaced usages of StringBuffer with StringBuilder instead
  • Fixed StringUtils padLeft/padRight comments
  • Added projections: getClassType(), getClassName(), getClassNameSimple()
  • Updated Objects.* predicates to use Object instead of T where a type is not needed
    (this is to alleviate some type inferencing woes with javac/ecj)
  • Added print() predicate to Objects and Strings
  • Added min() and max() to Linq
  • Added minOccurring() and maxOccurring() to Linq
    (using non-parallel map/reduce which needs to be optimised in a next version)
  • LocalDatePropertyMetadata

CHANGELOG 0.9.8

  • Ivy support
    You can now resolve the jpropel dependency by using in ivysettings.xml:

  • BouncyCastle support removed, without compromising AES, XTEA and Blowfish
    algorithms (although Rijndael was renamed to AES)

  • lombok-pg 0.10.4-SNAPSHOT support

  • Joda Period validation (see PeriodPropertyMetadata)

CHANGELOG 0.9.7

  • Added lock-free thread-safe initialisation guards, for preventing classes
    from being used without being initialised first (MultiInitGuard) and for
    preventing classes from being initialised multiple times (SingleInitGuard)
  • String crop() trim-like function allows for strings to be cropped of
    one or more specified characters. Example:

val result = StringUtils.crop(“abc123abc”, new char[] {‘a’,‘c’});
System.out.println(result); // => “bc123ab”

  • Linq.single() get a single element of a collection, throwing an exception
    if zero, two or more elements exist in the collection.
  • Cleaner functional invocation with InvokeOneArg and InvokeNoArgs classes.

CHANGELOG 0.9.6

  • Split up Predicates class into Objects, Strings, Arrays and Iterables
    for modularization
  • Function1 -> Predicate1
    Breaking change using the more appropriate annotation @Predicate instead
    of having to specify the return type for predicate-style functions
  • MapMultimap uses yield() when iterating
  • SharedMapMultimap: thread-safe version of MapMultimap

CHANGELOG 0.9.5

  • MapMultimap data structure

  • Better java.io.File extension methods

    new File(“myFile.txt”).readFileToEnd().split(“\r\n”);

CHANGELOG 0.9.4

  • Added a lot of new predicates and projections.
    e.g. instanceOf(), appendToFile(), copyFile(), deleteFile(), etc.

CHANGELOG 0.9.3

  • Using Scala-like programming-style library
    (https://github.com/peichhorn/lombok-pg)

    examples:

    // create alphabet char[]
    new Character(‘A’).to(new Character(‘Z’)).unbox();

    // join two arrays and put in list
    alphabet.join(numerics).toList();

    // select distinct j* names, using LINQ-style statements
    new String[] { “james”, “john”, “john”, “eddie” }.where(startsWith(“j”)).distinct();

    ** WARNING: **
    If you use Eclipse or NetBeans, patch it by running lombok.jar
    and selecting the executable. No patching required for javac / Ant

    Full example:

import java.util.Arrays;
import lombok.ExtensionMethod;
import lombok.val;
import propel.core.utils.Linq;
import propel.core.utils.StringUtils;
import static propel.core.functional.predicates.Strings.;
//import static propel.core.functional.projections.Projections.
;

@ExtensionMethod({Arrays.class, Linq.class, StringUtils.class})
public class Main
{

/**

  • @param args
    */
    public static void main(String[] args)
    {
    val names = new String[] { “john”, “james”, “john”, “eddie” }.where(startsWith(“j”)).distinct().all(println());
    }
    }
  • Added commonly used Predicates and Projections see
    propel.core.functional.Predicates, propel.core.functional.Projections

    examples:
    equal(), notEqual(), isNullOrEmpty(), startsWith(), etc.

  • Removed propel.core.threading.* as it has been superseded by
    JDK7 fork/join framework.

CHANGELOG 0.9.2

  • Annotation-based method-call tracing

    example: // This logs input args, result and exceptions (if any)
    // with fine-grained configurability in presentation of data
    @Trace(level=LogLevel.WARN)
    public int add(int a, int b) {…}

  • Stopwatch class allowing for high-precision performance benchmarking

    example: Stopwatch sw = new Stopwatch();
    sw.start();
    sw.stop();
    long ns = sw.getNanosElapsed();

  • Robust resource loading by classpath, supporting loading from within
    JARs, HTTP-based URLs as well as file-system, through the same API
    (see FileUtils)

    example: // this file could reside inside a JAR, or outside a JAR
    URL url = “/java/util/test.xml”.getResourceUrl();
    String xmlData = url.getResourceTextData();

         // read entire file 
         String xmlData = FileUtils.readFileToEnd(url.toUri().toUrl());
    
  • Tuples
    example: Pair<A,B> tuple1 = new Pair<A,B>(a,b);
    Triple<A,B,C> tuple2 = new Triple<A,B,C>(a,b,c);
    etc.

  • Bugfixes

    1. StringUtils: split() ignoring last character when using
      multi-char array separator
    2. SharedModuloCounterLight: getValue() always returned 0
    3. FileUtils: readFileToEnd() Windows memory leak fixed

CHANGELOG 0.9.1

  • ~100% code coverage
  • ~100% documentation & full checked Exception documentation

CHANGELOG 0.8

  • Bouncycastle encryption/decryption support added

  • CryptographicString class, allows for storing strings encrypted
    in memory. Accessing the string decrypts it, as char[] or byte[]

    example: // stores in memory encrypted
    CryptographicString cs = new CryptographicString(“my precious secret”);

    // access unencrypted version
    byte[] ba = cs.asByteArray();
    char[] ca = cs.asCharArray();
    String st = cs.asString(); // not recommended

CHANGELOG 0.7

  • Arrays utilities (ArrayUtils)
    example: // convert primitive array to the corresponding
    // wrapper type array e.g. int[] -> Integer[]
    Integer[] ints = new int[] { 1,2,3}.box();

         // inverse operation 
         int[] intsCopy = ints.unbox();
    
         // add/remove operations
         String[] strVals = new String[] { "hello", "hello2" };
         strVals = strVals.add("test");
         strVals = strVals.remove("test");
       
         // resize
         strVals.resize(1); // last element lost
         strVals.resize(strVals, 2); // last element is null
    
         // get part of array
         strVals = strVals.subArray(strVals, 0, 1); // single element
    
         // join and prepend 
         strVals = strVals.join(strVals).prepend("test");
    
  • Byte array utilities
    example: // convert multi-byte arithmetic structures
    ByteArrayUtils.getBytes(Long)

         // support for little and big endian
         ByteArrayUtils.LITTLE_ENDIAN 
    
  • Conversion utilities
    example: // convert various data types to BASE64
    ConversionUtils.toBase64(…)
    ConversionUtils.fromBase64…

         // hex conversions 
         ConversionUtils.toHex(...)
         ConversionUtils.fromHex...
    
         // binary conversions
         ConversionUtils.toBinary(...)
         ConversionUtils.fromBinary...
    
         // byte[] conversions
         ConversionUtils.toByteArray(...)
         ConversionUtils.toString(...)
    
         // alphanumeric conversions (e.g. for shortening)
         ConversionUtils.toAlphanumeric(...)
         ConversionUtils.fromAlphanumeric...
    
         // human-readable intervals, e.g. 2:10:23 -> 2 hours ago
         ConversionUtils.toHumanReadable(...)
    
  • Escaping
    example: // escape HTML
    EscapingUtils.toHtml(…)
    EscapingUtils.fromHtml(…)

         // escape XML
         EscapingUtils.toXml(...)
         EscapingUtils.fromXml(...)
    
         // URL escaping
         EscapingUtils.toUrl(...)
         EscapingUtils.fromUrl(...);
    
  • File utilities
    example: // append text to a file, if missing it is created
    FileUtils.appendText(…);

         // read entire file in memory (as text)
         FileUtils.readToEnd(...)
    
         // read entire file in memory (as byte[])
         FileUtils.readFileInMemory(...) 
         
         // deletion
         FileUtils.delete(...) // throws exception upon failure
         FileUtils.tryDelete(...) // no exceptions thrown
    
         // touch file
         FileUtils.touch(...) // create or update
    
         // search for file, highly configurable for:
         // - files/folders or both
         // - hidden/normal or both
         // - sorting order (ascending/descending/none)
         // - traversal (depth/breadth/shallow)
         FileUtils.scanPath(...) 
    
         // test read/write and access right for a path
         FileUtils.tryPerformCreateReadWriteDeleteAccess("C:\\");
    
         // forensically copy file (maintains MAC dates)
         FileUtils.cloneFile(from, to);
    
  • Operating System utils
    example: // OS detection
    boolean tux = OsUtils.isLinux();
    boolean win = OsUtils.isWindows();
    boolean bsd = OsUtils.isBsd();
    boolean osx = OsUtils.isOSX();

  • Randomisation utilities
    example: // one-liner for a pseudo random
    RandomUtils.getPseudoInt32(…)
    RandomUtils.getPseudoInt64(…)

         // one-liner for a secure random
         RandomUtils.getSecureInt32(...) 
         RandomUtils.getSecureInt64(...) 
    
         // one-liner for pseudo alphanumeric text
         RandomUtils.getPseudoAlphanumericText(...)
    
         // one-liner for secure, arbitratily-sized byte array
         RandomUtils.getSecureBytes(...) 
    
         // one-liner for a pseudorandom BASE64 
         RandomUtils.getPseudoBase64(...);
    
  • Reflection utilities
    example: // instantiate class by name of class type
    ReflectionUtils.activate(…)

         // check if two methods, fields, properties or constructors
         // appear to be the same (via signature comparison)
         ReflectionUtils.equal(...) 
    
         // get all declared and/or inherited annotations
         ReflectionUtils.findAnnotations(...) 
    
         // discover bean properties
         PropertyInfo pi = ReflectionUtils.getProperty("name");
    
         // search all fields, methods and properties
         ReflectionUtils.getMember(A.class, "name", true);
    
         // check if an interface is implemented
         ReflectionUtils.isImplementing(A.class, Serializable.class);
    
         // check if class extends another class
         ReflectionUtils.isExtending(Client.class, Person.class);
    
         // check if a class "looks like a duck" (duck-typing)
         ReflectionUtils.isLookingLike(A.class, B.class);
    
         // one-liner proxying
         ReflectionUtils.proxy(myObj, MyInterfaceType.class);
    
  • Streams
    example: // copy stream contents
    StreamUtils.copy(inputStream, outputStream, size);

         // block until read a specified number of bytes from stream
         StreamUtils.readFully(inputStream, 100);
    
         // block until read a specified number of chars from stream
         StreamUtils.readAllCharacters(stream, 100);
    
         // read stream until a byte or char is encountered
         StreamUtils.readUntil(inputStream, "\r\n.\r\n");
    
         // skip bytes 
         StreamUtils.skipBytes(inputStream, 100);
    
         // skip characters
         StreamUtils.skipBytes(inputStream, 100); 
    
         // chunked writing / reading from streams
         byte[] data = ...
         int chunkSize = 1024;
         StreamUtils.writeFully(outputStream, data, chunkSize);
    
  • String utilities
    example: // char range generation
    StringUtils.charRange(65, 91); // chars A…Z

         // String comparison implementations:
         // e.g. this returns true for German locale
         equal("stra�e", "strasse", StringComparison.CurrentCulture)
         // and this returns true
         startsWith("str", "STR", StringComparison.OrdinalIgnoreCase) 
       
         // single method to check for null or ""
         isNullOrEmpty(String) 
    
         compare(...)
         concat(...)
         contains(...)
         containsAny(...)
         containsAll(...)
         TODO: document more functions here          
    

#CHANGELOG 0.6

  • SLF4J logging

#CHANGELOG 0.5

  • Validation framework
    example: // validate a last name
    StringPropertyMetadata strMeta = new
    StringPropertyMetadata(“Last name”, 3, 50, true, true, true);

         // ValidationException: "Last name cannot be null"
         strMeta.validate(null); 
    
         // ValidationException: "Last name cannot be empty"
         strMeta.validate(""); 
    
         // "Last name cannot have fewer than 3 characters in length"
         strMeta.validate("ab"); 
    
         // "Last name cannot contain the null character"
         strMeta.validate("abc\0def"); 
    
         // "Last name cannot be over 50 characters in length"
         strMeta.validate("...51 chars here..."); 
    

    others: All basic data types (int, double, String, boolean, etc.)
    File names and folders (cross platform)
    File system paths (cross platform)
    Domain names (to RFC spec)
    Sub-domain names (to RFC spec)
    Emails (to RFC spec)
    Active Directory usernames (LDAP spec)
    CreditCard
    IPv4
    IPv6
    MAC addresses

#CHANGELOG 0.4

  • Transactions

    example: // transactionally swap two files, by using a temp file,
    // in the case that an error occurs roll back all actions
    String src=“/home/test1.txt”;
    String dst=“/home/test2.txt”;

         // used for the swap process
         String temp = "/home/temp.txt";
    
         TransactionManager tm = new TransactionManager();               
    
         // action is to move source file to a temp location, 
         // rollback action is to move the temp file back to source
         tm.add(moveFileAction(src, temp), 
                moveFileAction(temp, src));
    
         // action is to move destination file to source, 
         // rollback action is to move source to destination
         tm.add(moveFileAction(dst, src),
                moveFileAction(src, dst));
    
         // this is the last action, no rollback action required
         tm.add(moveFileAction(temp, dst));
    
         // safely swap files
         tm.commitWithRollback();
    
         // ... somewhere outside method scope ...
         @Function
         private Void moveFileAction(final String src, final String dest)
         {
            File file = new File(src);
            file.moveTo(dest);
         }
    

    others: commit();
    rollback();
    commitWithRollback();
    resumeCommit();
    resumeRollback();
    skipCommitStep();
    skipRollbackStep();

#CHANGELOG 0.3

  • Parallel task library

    example: // declare a simple printing task
    ParallelAction pa = new ParallelAction(){
    public void executeWith(Integer arg) {
    for(int i=0; i < arg; i++)
    System.out.println(i);
    }
    };

         // background execution
         pa.executeLater();
    
         // blocking execution
         pa.executeAndWait();
    

    example: // declare a simple function
    ParallelFunction<Integer, Double> pf =
    new ParallelAction<Integer, Double>(){
    public Double operateOn(Integer arg) {
    Double dbl = new Double(arg);
    return Math.exp(dbl);
    }
    };

         // background execution
         ITaskResult<Double> result = Linq.first(pf.executeLater()));
         if(!result.isSuccessful())
            throw new Exception("Could not perform calculation", 
                                result.getError());
         
         // print result
         System.out.println(result.getResult());                  
    

    example: // actions and functions can be grouped into collections
    ParallelActionCollection pac =
    new ParallelActionCollection();
    pac.addAction(…);
    pac.addAction(…);

         // wait for all to complete
         pac.executeAndWaitAll();
    
         // background execution (e.g. reverse order)
         for(ITaskResult<String> result :
             pf.executeAndYield(TaskResultOrder.ReverseOrder)) {
           if(!result.isSuccessful())
              // tasks are identified and any errors are preserved
              throw new Exception("Could not perform calculation with "
                 + "ID="+result.getTaskId(), result.getError());
    
              System.out.println(result.getResult());                  
         }
    

    others: Cancellable actions and functions:
    These give the ability to stop a task mid-way.

         Timed actions and functions:
         Automatically stop if a configurable amount of time passes.
    

#CHANGELOG 0.2

  • Linq for Java

    example: Iterable someStrings = …
    int count = Linq.count(someStrings);

    example: // simulate: String[] names = people.select(p=>p.toString()).reverse()
    Person[] people = …
    String[] peopleNames = people.select(toStringSelector()).reverse();

         // ... somewhere else in code, declaration of method
         @Function
         private String toStringSelector(Person person) {
            return person.toString();
         }
    
    others:  aggregate();
             all();
             any();
             cast();
             concat();
             contains();
             containsAll();
             containsAny();
             count();
             countWhere();
             defaultIfEmpty();
             distinct();
             elementAt();
             elementAtOrDefault();
             except();
             first();
             firstOrDefault();
             ...
             select();
             ...
             toArray();
             ...
             where();
             zip();
             // most things you expect from LINQ have been implemented
    

#CHANGELOG 0.1.2

  • CONSTANTS class

    example: CONSTANT.CRLF // this equals to “\r\n”
    CONSTANT.ENVIRONMENT_NEWLINE // “\r\n” on Windows, “\n” on *nix
    CONSTANT.DIRECTORY_SEPARATOR // “\” for Windows, “/” for *nix
    CONSTANT.EMPTY_STRING // same as “”
    CONSTANT.ZERO_GUID // “00000000-0000-0000-0000-000000000000”
    CONSTANT.A // “A”
    CONSTANT.a // “a”
    CONSTANT.ONE // “1”
    // etc.

#CHANGELOG 0.1.1

  • More collections

    example: // AVL-backed hashtable implementation.
    // AVL trees are the fastest BSTs for lookups
    AvlHashtable<Long, Person> idToPersonMap =
    new AvlHashtable<Long, Person>(){};
    idToPersonMap.add(123, new Person());
    Person person = idToPersonMap.get(123);

    example: Person[] arrayPeople = …
    // implements Iterable
    ReifiedArray people =
    new ReifiedArray(arrayPeople);

    example: // Least-Recently Used algorithm buffer
    LRUBuffer buffer = new LRUBuffer(2){};
    buffer.add(“1”);
    buffer.add(“2”);
    buffer.add(“3”); // buffer contains only “2”, “3” now (LRU)

#CHANGELOG 0.1

  • Reified collections

    example: ReifiedList people = new ReifiedArrayList() {};
    -or- people = new ReifiedArrayList(Person.class);

         // using plain List this would be: Object[] array = ... 
         Person[] array = people.toArray(); 
    
  • Concurrent collections
    example: // queue used for message passing (MPI) between producers/consumers
    SharedQueue queue = new SharedQueue();
    queue.get(…);

         // another thread
         queue.put(...);  // this signals the other waiting thread
    

    Summary of CORE Features

    • Reified collections, arrays and iterables, inheriting from a single
      interface, using the super-type token approach
    • Linq-like functionality for Java, overloaded methods for arrays and
      iterables, the latter using “yield” generators
    • Parallel task-oriented library, supporting single & collection of tasks,
      time-expiring and cancellable tasks, blocking and background tasks,
      pipelining, thread re-use, etc.
    • Support for functional programming e.g. actions, functions, predicates
    • Many collection types, e.g. concurrent collections, buffers and queues,
      support for producer/consumer message passing
    • Further collection types include AVL hashtable, LRU buffer, time
      expiring session, bi-map, circular buffer and others
    • Tons of conversion helpers such as hex, binary, octal, byte array,
      string, UTF8, Base64, etc.
    • Constants class, holding most common constants used e.g. letters,
      numbers, unicode symbols, newlines, OS-dependent stuff such as
      directory & path separators, etc.
    • Validation framework, extensible and easy to use. Support of common
      types out of the box, e.g. date/time, string, numeric, etc.
    • Tracing tools for automatic argument and return-type logging.
    • Profiling helper classes with nanosecond precision
    • Counters of all kinds, e.g. thread-safe, lock-free, single-threaded
    • Observer pattern implementation with support for auto de-registration
      upon the event of notification failure
    • Stack trace logging helper
    • Convention over configuration, but highly configurable