{title:'Object Tools', created:'9.0.0'}

The {@link oaj.objecttools} package defines convenience utility classes for accessing and manipulating POJOs. It consists of the following classes:

ObjectRest

The {@link oaj.objecttools.ObjectRest} class provides the ability to perform standard REST operations (GET, PUT, POST, DELETE) against nodes in a POJO model. Nodes in the POJO model are addressed using URLs.

A POJO model is defined as a tree model where nodes consist of consisting of the following:

Leaves of the tree can be any type of object.

Use {@link oaj.objecttools.ObjectRest#get(String) get()} to retrieve an element from a JSON tree.
Use {@link oaj.objecttools.ObjectRest#put(String,Object) put()} to create (or overwrite) an element in a JSON tree.
Use {@link oaj.objecttools.ObjectRest#post(String,Object) post()} to add an element to a list in a JSON tree.
Use {@link oaj.objecttools.ObjectRest#delete(String) delete()} to remove an element from a JSON tree.

Example:

| // Construct an unstructured POJO model | JsonMap map = JsonMap.ofJson("" | + "{" | + " name:'John Smith', " | + " address:{ " | + " streetAddress:'21 2nd Street', " | + " city:'New York', " | + " state:'NY', " | + " postalCode:10021 " | + " }, " | + " phoneNumbers:[ " | + " '212 555-1111', " | + " '212 555-2222' " | + " ], " | + " additionalInfo:null, " | + " remote:false, " | + " height:62.4, " | + " 'fico score':' > 640' " | + "} " | ); | | // Wrap Map inside an ObjectRest object | ObjectRest johnSmith = ObjectRest.create(map); | | // Get a simple value at the top level | // "John Smith" | String name = johnSmith.getString("name"); | | // Change a simple value at the top level | johnSmith.put("name", "The late John Smith"); | | // Get a simple value at a deep level | // "21 2nd Street" | String streetAddress = johnSmith.getString("address/streetAddress"); | | // Set a simple value at a deep level | johnSmith.put("address/streetAddress", "101 Cemetery Way"); | | // Get entries in a list | // "212 555-1111" | String firstPhoneNumber = johnSmith.getString("phoneNumbers/0"); | | // Add entries to a list | johnSmith.post("phoneNumbers", "212 555-3333"); | | // Delete entries from a model | johnSmith.delete("fico score"); | | // Add entirely new structures to the tree | JsonMap medicalInfo = JsonMap.ofJson("" | + "{" | + " currentStatus: 'deceased'," | + " health: 'non-existent'," | + " creditWorthiness: 'not good'" | + "}" | ); | johnSmith.put("additionalInfo/medicalInfo", medicalInfo);

In the special case of collections/arrays of maps/beans, a special XPath-like selector notation can be used in lieu of index numbers on GET requests to return a map/bean with a specified attribute value.
The syntax is {@code @attr=val}, where attr is the attribute name on the child map, and val is the matching value.

Example:

| // Get map/bean with name attribute value of 'foo' from a list of items | Map map = objectRest.getMap("/items/@name=foo");

ObjectSearcher

The {@link oaj.objecttools.ObjectSearcher} class is designed to provide searches across arrays and collections of maps or beans. It allows you to quickly filter beans and maps using simple yet sophisticated search arguments.

Example:

| MyBean[] arrayOfBeans = ...; | ObjectSearcher searcher = ObjectSearcher.create(); | | // Returns a list of beans whose 'foo' property is 'X' and 'bar' property is 'Y'. | List<MyBean> result = searcher.run(arrayOfBeans, "foo=X,bar=Y");

The tool can be used against the following data types:

The default searcher is configured with the following matcher factories that provides the capabilities of matching against various data types. This list is extensible:

The {@link oaj.objecttools.StringMatcherFactory} class provides searching based on the following patterns:

The {@link oaj.objecttools.NumberMatcherFactory} class provides searching based on the following patterns:

The {@link oaj.objecttools.TimeMatcherFactory} class provides searching based on the following patterns:

ObjectSorter

The {@link oaj.objecttools.ObjectSorter} class is designed to sort arrays and collections of maps or beans.

Example:

| MyBean[] arrayOfBeans = ...; | ObjectSorter sorter = ObjectSorter.create(); | | // Returns a list of beans sorted accordingly. | List<MyBean> result = sorter.run(arrayOfBeans, "foo,bar-");

The tool can be used against the following data types:

The arguments are a simple comma-delimited list of property names optionally suffixed with '+' and '-' to denote ascending/descending order.

ObjectViewer

The {@link oaj.objecttools.ObjectViewer} class is designed to extract properties from collections of maps or beans.

Example:

| MyBean[] arrayOfBeans = ...; | ObjectViewer viewer = ObjectViewer.create(); | // Returns the 'foo' and 'bar' properties extracted into a list of maps. | List<Map> result = viewer.run(arrayOfBeans, "foo,bar");

The tool can be used against the following data types:

ObjectPaginator

The {@link oaj.objecttools.ObjectPaginator} class is designed to extract sublists from arrays/collections of maps or beans.

Example:

| MyBean[] arrayOfBeans = ...; | ObjectPaginator paginator = ObjectPaginator.create(); | | // Returns all rows from 100 to 110. | List<MyBean> result = paginator.run(arrayOfBeans, 100, 10);

The tool can be used against the following data types:

ObjectIntrospector

The {@link oaj.objecttools.ObjectIntrospector} class is used to invoke methods on {@code Objects} using arguments in serialized form.

Example:

| String string1 = "foobar"; | String string2 = ObjectIntrospector | .create(string) | .invoke(String.class, "substring(int,int)", "[3,6]"); // "bar"

The arguments passed to the identified method are POJOs serialized in JSON format. Arbitrarily complex arguments can be passed in as arguments.

ObjectMerger

The {@link oaj.objecttools.ObjectMerger} class is used for merging POJOs behind a single interface. This is particularly useful in cases where you want to define beans with 'default' values.

For example, given the following bean classes:

| public interface IA { | String getX(); | void setX(String x); | } | | public class A implements IA { | private String x; | | public A(String x) { | this.x = x; | } | | public String getX() { | return x; | } | | public void setX(String x) { | this.x = x; | } | }

The getters will be called in order until the first non-null value is returned:

| merge = ObjectMerger.merger(IA.class, new A("1"), new A("2")); | assertEquals("1", merge.getX()); | | merge = ObjectMerger.merger(IA.class, new A(null), new A("2")); | assertEquals("2", merge.getX()); | | merge = ObjectMerger.merger(IA.class, new A(null), new A(null)); | assertEquals(null, merge.getX());