Class Struct

java.lang.Object
com.randomnoun.common.Struct

public class Struct extends Object
Encoder/decoder of JavaBeans and 'structured' maps and lists. A structured map or list is any Map or List that satisfies certain conventions, listed below.

A structured map is any implementation of the Map interface, in which every key is a String, and every value is either a primitive wrapper type (String, Long, Integer, etc...), a structured map or a structured list. A structured list is any implementation of the List interface, of which every value is a primitive wrapper type, a structured map or a structured list.

In this way, arbitrarily complex objects can be created and passed between Struts code and the business layer, or Struts code and the JSP layer, without resorting to the creation of application-specific datatypes. These datatypes are also used by the Spring JdbcTemplate framework to return values from a database, so it is useful to have some generic functions that operate on them.

Author:
knoxg
  • Field Details

  • Constructor Details

  • Method Details

    • sortStructuredList

      public static void sortStructuredList(List list, String keyField)
      Sorts a structured list on the supplied key field
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalStateException - if the list is not composed of Maps
    • sortStructuredListIgnoreCase

      public static void sortStructuredListIgnoreCase(List list, String keyField)
      Sorts a structured list on the supplied key field; the key value is sorted case-insensitively (it must be of type String or a ClassCastException will occur).
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalStateException - if the list is not composed of Maps
    • setFromRequest

      public static void setFromRequest(Object obj, jakarta.servlet.http.HttpServletRequest request)
      Set all fields in object 'obj' using values in request. Each request parameter is checked against the object to see if a bean setter method exists for that parameter name. If it does, then it is invoked, using the parameter value as the setter argument. This method uses the setValue(Object, String, Object, boolean, boolean, boolean) method to dynamically create map and list elements as required if the object being set implements the Map interface.

      e.g. if passed a Map object, and the HttpServletRequest has a parameter named "table[12].id" with the value "1234", then:

      • a List object named "table" is created in the Map,
      • the list is increased to allow at least 12 elements,
      • that element is set to a new Map object ...
      • ... which contains the String key "id", which is assigned the value "1234".

      This processing allows developers to pass arbitrarily complex structures through from HttpServletRequest name/value pairs.

      This method operates on both structured objects (Maps/Lists) or data-transfer objects (DTOs). For example, if passed a bean-like Object which had a getTable() method that returned a List, then this would be used to perform the processing above. (If the List returned a Map at index 12, then an 'id' key would be created as before; if the List returned another Object at index 12, then the setId() method would be called instead; if the list returned null at index 12, then a Map would be created as before).

      NB: If an object is not a Map, and does not have the appropriate setter() method, then this function will *not* raise an exception. This is intentional behaviour - (use setValue(Object, String, Object, boolean, boolean, boolean) if you need more fine-grained control.

      You can limit the setters that are invoked by using the setFromRequest(Object, HttpServletRequest, String[]) form of this method.

      Parameters:
      obj - The object being set.
      request - The request containing the source data
      Throws:
      RuntimeException - if an invocation target exception occurred whilst calling the object's set() methods.
    • setFromRequest

      public static void setFromRequest(Object obj, jakarta.servlet.http.HttpServletRequest request, String[] fields)
      Set all fields in object 'obj' using values in request. Only the request parameter names passed in through the 'fields' argument will be used to populate the object. If the named parameter does not exist in the request, then the setter for that parameter is not invoked.

      See setFromRequest(Object, HttpServletRequest) for more information on how this method operates.

      Parameters:
      obj - The object being set.
      request - The request containing the source data
      fields - An array of strings, denoting the fields that are sourced from the request. All other parameters in the request are ignored.
      Throws:
      RuntimeException - if an invocation target exception occurred whilst calling the object's set() methods.
    • setFromMap

      public static void setFromMap(Object obj, Map map, boolean ignoreMissingSetter, boolean convertStrings, boolean createMissingElements)
      Similar to the setFromRequest(Object, HttpServletRequest) method, but uses a Map instead of a request.
      Parameters:
      obj - The object being set.
      map - The Map containing the source data
      ignoreMissingSetter - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      convertStrings - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      createMissingElements - passed to setValue(Object, String, Object, boolean, boolean, boolean)
    • setFromMap

      public static void setFromMap(Object obj, Map map, boolean ignoreMissingSetter, boolean convertStrings, boolean createMissingElements, String[] fields)
      Similar to the setFromRequest(Object, HttpServletRequest, String[]) method, but uses a Map instead of a request.
      Parameters:
      obj - The object being set.
      map - The Map containing the source data
      ignoreMissingSetter - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      convertStrings - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      createMissingElements - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      fields - An array of strings, denoting the fields that are sourced from the request. All other parameters in the request are ignored.
    • setFromObject

      public static void setFromObject(Object targetObj, Object sourceObj, boolean ignoreMissingSetter, boolean convertStrings, boolean createMissingElements, String[] fields)
      Similar to the setFromRequest(Object, HttpServletRequest, String[]) method, but uses a Map instead of a request.
      Parameters:
      targetObj - The object being set.
      sourceObj - The Map containing the source data
      ignoreMissingSetter - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      convertStrings - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      createMissingElements - passed to setValue(Object, String, Object, boolean, boolean, boolean)
      fields - An array of strings, denoting the fields that are sourced from the request. All other parameters in the request are ignored.
    • getValue

      public static Object getValue(Object object, String key)
      Return a single value from a structured map. Returns null if the value does not exist, or if an error occurred retrieving it.
      Parameters:
      object - The structure map
      key - The key of the value we wish to retrieve (e.g. "abc.def[12].ghi")
      Returns:
      The value
    • setValue

      public static void setValue(Object object, String key, Object value, boolean ignoreMissingSetter, boolean convertStrings, boolean createMissingElements) throws NumberFormatException
      Sets a single value in a structured object. The object may be composed of javabean-style objects, Map/List classes, or a combination of the two.

      There is a possible denial-of-service attack that can be used against this method which you should probably be aware of, but can't do anything about: if a large list index is supplied, e.g. "abc[1293921]", then a list will be generated with this many elements in it. There are workarounds for this, but none are really satisfactory.

      It should also be noted that even if an exception is thrown within this method, the data structure underneath it may still have been modified, e.g. setting "abc.def.ghi" may successfully construct 'def' but later fail on 'ghi'.

      Parameters:
      object - The structure map or list
      key - The key of the value we wish to set (e.g. "abc.def[12].ghi"). Note that map keys are assumed; i.e. they are not enclosed in 'curly braces'.
      value - The value to set this to
      ignoreMissingSetter - If we are asked to set a value in an object which does not have an appropriate setter, don't raise an exception (just does nothing instead).
      convertStrings - If we are asked to set a string value in an object which has a setter, but of a different type (e.g. setCustomerId(Long)), performs conversions to that type automatically. (Useful when setting values sourced from a HttpServletRequest, which will always be of String type).
      createMissingElements - If we are asked to set a value in a Map or List that does not exist, will create the required Map keys or extend the List so that the value can be set.
      Throws:
      IllegalArgumentException - if
      • An null map or list is navigated down
      • A non-List object is invoked with the '[]' operator
      • A non-Map object is invoked with the '.' operator, or the object has no getter/setter method with the appropriate name
      • An empty mapped property is supplied e.g. bob..something
      • An invalid key was supplied (e.g. 'bob[123' -- no closing square bracket)
      NumberFormatException - if an array index cannot be converted to an integer via Integer.parseInt(java.lang.String).
    • setListElement

      public static void setListElement(List list, int index, Object object)
      Sets the element at a particular list index to a particular object. This differs from the standard List.set() method inasmuch as the list is allowed to grow in the case where index>=List.size(). If the list needs to grow to accomodate the new element, then null objects are appended until the list is large enough.
      Parameters:
      list - The list to modify
      index - The position within the list we wish to set to this object
      object - The object to be placed into the list.
    • getStructuredListItem

      public static Map getStructuredListItem(List list, String keyField, long longValue)
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      longValue - The key value to search for
      Returns:
      The requested element in the list, or null if the element cannot be found.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalStateException - if the list is not composed of Maps
    • getStructuredListObject

      public static Object getStructuredListObject(List list, String keyField, long longValue)
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      longValue - The key value to search for
      Returns:
      The requested element in the list, or null if the element cannot be found.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalStateException - if the list is not composed of Maps
    • getStructuredListItem

      public static Map getStructuredListItem(List list, String keyField, Object key)
      Searches a structured list for a particular row. The list is presumed to be a List of Maps, each of which contains a key field. Lists are searched sequentially until the desired row is found. It is permitted to search on null key values. If the row cannot be found, null is returned.

      For example, in the list:

        list = [
          0: { systemId = "abc", systemTimezone = "dalby" }
          1: { systemId = "def", systemTimezone = "london" }
          2: { systemId = "ghi", systemTimezone = "new york" }
        ]
        

      getStructuredListItem(list, "systemId", "def") would return a reference to the second element in the list, i.e. the Map:

        { systemId = "def", systemTimezone = "london" }
        
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      key - The key value to search for
      Returns:
      The requested element in the list, or null if the element cannot be found.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalArgumentException - if the list is not composed of Maps
    • getStructuredListItem2

      public static Map getStructuredListItem2(List list, String keyField, long longValue, String keyField2, long longValue2)
      As per getStructuredListItem(List, String, long), with a compound key.
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      longValue - The key value to search for
      keyField2 - The name of the second key field.
      longValue2 - The second key value to search for
      Returns:
      The requested element in the list, or null if the element cannot be found.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalStateException - if the list is not composed of Maps
    • getStructuredListObject

      public static Object getStructuredListObject(List list, String keyField, Object key)
      Searches a structured list for a particular row. The list may be composed of arbitrary objects.
      Parameters:
      list - The list to search.
      keyField - The name of the key field.
      key - The key value to search for
      Returns:
      The requested element in the list, or null if the element cannot be found.
      Throws:
      NullPointerException - if list or keyField is set to null.
      IllegalArgumentException - if the list is not composed of Maps
    • getStructuredListColumn

      public static List getStructuredListColumn(List list, String columnName)
      Searches a structured list for a particular column. The list is presumed to be a List of Maps, each of which contains a particular key. The value of this key is retrieved from each Map, and added to a new List, which is then returned to the user. If the value of that key is null for a particular Map, then the null value is added to the returned list.

      For example, in the list:

        list = [
          0: { systemId = "abc", systemTimezone = "dalby" }
          1: { systemId = "def", systemTimezone = "london" }
          2: { systemId = "ghi", systemTimezone = "new york" }
          3: null
          4: { systemId = "jkl", systemTimezone = "melbourne" }
        ]
        

      getStructuredListColumn(list, "systemId") would return a new List with three elements, i.e.

        list = [
          0: "abc"
          1: "def"
          2: "ghi"
          3: null
          4: "jkl"
        ]
        
      Parameters:
      list - The list to search.
      columnName - The key of the entry in each map to retrieve
      Returns:
      a List of Objects
      Throws:
      NullPointerException - if list or columnName is set to null.
    • structuredListToString

      public static String structuredListToString(String topLevelName, List list)
      This method returns a human-readable version of a structured list. The output of this list looks similar to the following:
         topLevelName = [
           0: 'stringValue'
           1: null
           2: (WeirdObjectClass) "toString() output of weirdObject"
           3 = {
               mapElement => ...,
               ...
             }
           4 = [
               0: listElement
               ...
             ]
           5 = (
               setElement
           )
           ...
         ]
       
      Strings are represented as their own values in quotes; null values are represented with the text null, and structured maps and structured lists contained within this list are recursed into.
      Parameters:
      topLevelName - The name to assign to the list in the first row of output
      list - The list we wish to represent as a string
      Returns:
      A human-readable version of a structured list
    • structuredSetToString

      public static String structuredSetToString(String topLevelName, Set set)
      This method returns a human-readable version of a structured set. The output of this set looks similar to the following:
         topLevelName = (
           0: 'stringValue'
           1: null
           2: (WeirdObjectClass) "toString() output of weirdObject"
           3 = {
               mapElement => ...,
               ...
             }
           4 = [
               0: listElement
               ...
             ]
           5 = (
               setElement
             )
           ...
         )
       
      Strings are represented as their own values in quotes; null values are represented with the text null, and structured maps and structured lists contained within this list are recursed into.
      Parameters:
      topLevelName - The name to assign to the list in the first row of output
      set - The set we wish to represent as a string
      Returns:
      A human-readable version of a structured list
    • structuredMapToString

      public static String structuredMapToString(String topLevelName, Map map)
      This method returns a human-readable version of a structured map. The output of this list looks similar to the following:
         topLevelName = {
           apples => 'stringValue'
           rhinocerouseses => null
           weirdObjectValue => (WeirdObjectClass) "toString() output of weirdObject"
           mapValue = {
               mapElement => ...
               ...
             }
           listValue = [
               0: listElement
               ...
             ]
           setValue = (
               setElement
             )
           ...
         ]
       
      Keys within the map are sorted alphabetically before being enumerated. Strings are represented as their own values in quotes; null values are represented with the text null, and structured maps and structured lists contained within this list are recursed into.
      Parameters:
      topLevelName - The name to assign to the list in the first row of output
      map - The map we wish to represent as a string
      Returns:
      A human-readable version of a structured map
    • arrayToString

      public static String arrayToString(String topLevelName, Object list)
      This method returns a human-readable version of an array object that contains structured lists/maps/sets. Bear in mind that the array object itself isn't considered 'structured' by the definitions at the top of this class, or at least, it won't until this is added to the other structured parsers/readers.
         topLevelName[] = [
           0: 'stringValue'
           1: null
           2: (WeirdObjectClass) "toString() output of weirdObject"
           3 = {
               mapElement => ...,
               ...
             }
           4 = [
               0: listElement
               ...
             ]
           5 = (
               setElement
           )
           ...
         ]
       
      Strings are represented as their own values in quotes; null values are represented with the text null, and structured maps and structured lists contained within this list are recursed into.
      Parameters:
      topLevelName - The name to assign to the list in the first row of output
      list - The list we wish to represent as a string
      Returns:
      A human-readable version of a structured list
    • structuredListToJson

      public static String structuredListToJson(List list)
      Converts a java List into javascript
      Parameters:
      list - the list to convert into javascript
      Returns:
      the javascript version of this list.
    • structuredListToJson

      public static String structuredListToJson(List list, String jsonFormat)
      Converts a java List into javascript
      Parameters:
      list - the list to convert into javascript
      Returns:
      the javascript version of this list.
    • structuredListToJson

      public static void structuredListToJson(Writer w, List list, String jsonFormat) throws IOException
      Throws:
      IOException
    • structuredMapToJson

      public static String structuredMapToJson(Map map)
      Converts a java map into javascript
      Parameters:
      map - the Map to convert into javascript
      Returns:
      a javascript version of this Map
    • structuredMapToJson

      public static String structuredMapToJson(Map map, String jsonFormat)
      Converts a java map into javascript
      Parameters:
      map - the Map to convert into javascript
      Returns:
      a javascript version of this Map
    • structuredMapToJson

      public static void structuredMapToJson(Writer w, Map map, String jsonFormat) throws IOException
      Throws:
      IOException
    • structuredListToFilteredJson

      public static String structuredListToFilteredJson(List list, String jsonFormat, String... validKeys)
      Converts a java List into javascript, whilst filtering the keys of any Maps to only those in validKeys
      Parameters:
      list - the list to convert into javascript
      jsonFormat - the jsonFormat
      validKeys -
      Returns:
      the javascript version of this list.
    • structuredMapToFilteredJson

      public static String structuredMapToFilteredJson(Map map, String jsonFormat, String... validKeys)
      Converts a java Map into javascript, whilst filtering the keys of any Maps to only those in validKeys
      Parameters:
      map - the map to convert into javascript
      jsonFormat - the jsonFormat
      validKeys -
      Returns:
      the javascript version of this list.
    • structuredListToFilteredJson

      public static void structuredListToFilteredJson(Writer w, List list, String jsonFormat, String... validKeys) throws IOException
      Throws:
      IOException
    • structuredMapToFilteredJson

      public static void structuredMapToFilteredJson(Writer w, Map map, String jsonFormat, String... validKeys) throws IOException
      Throws:
      IOException
    • toDate

      public static String toDate(Date d, String jsonFormat)
      Convert a date object to it's JSON representation.

      As there's no real standard for this, a type format is used to define what kind of Dates your going to get on the Json side.

      Parameters:
      d - a Date object
      jsonFormat - either "microsoft" or "numeric"
      Returns:
      A date in json representation.
      See Also:
    • newStructuredMap

      public static Map<String,Object> newStructuredMap(Object... keyValuePairs)
      Create a structured Map out of key / value pairs. Keys must be Strings.

      So the value of Struct.newStructuredMap("thing", 1L, "otherThing", "value"); is a map with two entries:

      • an entry with key "thing" and value new Long(1), and
      • an entry with key "otherThing" and value "value".
      Parameters:
      keyValuePairs - a list of key / value pairs
      Returns:
      a Map as described above
      Throws:
      ClassCastException - if any of the supplied keys is not a String
    • renameStructuredListColumn

      public static void renameStructuredListColumn(List<Map<String,Object>> rows, String srcColumnName, String destColumnName)
      Rename a structured column, as returned from a Spring JdbcTemplate query. This method will iterate throw all rows of a table, replacing any srcColumnName keys with destColumnName
      Parameters:
      rows - the table being modified
      srcColumnName - the name of the row key (column) being replaced
      destColumnName - the new name of the row key (column)
    • addStructuredListColumn

      public static void addStructuredListColumn(List<Map<String,Object>> rows, String newColumnName, Object value)
      Add a structured column containing a constant value. This method will iterate through all rows of a table, adding a new newColumnName key with the supplied value.
      Parameters:
      rows - the table being modified
      newColumnName - the name of the row key (column) being added
      value - the value to add to the row