excelExporter.excelParser.dataModel

## Class ObjectMap<T>

- java.lang.Object
- - java.util.AbstractMap<java.lang.Object,java.lang.Object>
  - - excelExporter.excelParser.dataModel.ObjectMap<T>

- All Implemented Interfaces:
    java.util.Map<java.lang.Object,java.lang.Object>
  Direct Known Subclasses:
    Cluster, ExcelWorkbook, RowObject, RowObjectContainer

      public class ObjectMap<T>
      extends java.util.AbstractMap<java.lang.Object,java.lang.Object>

  This is the base class of most elements in the data model, a map of objects, which is compliant with the interface of the StringTemplate V4 engine. Such a map offers arbitrary data elements from the parsed input next to fixed, predefined elements, which support the data model.

  The class extends the Java Map. The map values are the data items from the parsed input which can thus be accessed directly by name from a StringTemplate V4 template, by using separating dots similar to the notation of fields in Java objects.

  Most objects of the data model are instances of this kind of container. The idea is to access the data items in the container under their natural name. As an example, if the container is the representation of an Excel workbook then the principal data items are the worksheets of that book and they could be accessed by name. Be the workbook "myBook" and have it two worksheets, named "mySheetA" and "mySheetB". From a StringTemplate V4 template one could access the parsed data like `<myBook.mySheetA>` or `<myBook.mySheetB>`.

  This way to access dynamic data (the names of the "fields" of `myBook` are determined by the application input) is convenient and in the template syntactically very close to the conventional StringTemplate data model, which is a predefined Java data structure consisting of nested Java classes having public fields of predefined names. In either case the dot notation is used in the template.

  The major difference between this container class and the conventional data model is the inaccessibility of additional public fields. For map objects the StringTemplate V4 template engine only supports the map lookup but not the "normal" introspection for public fields of requested name. If we extend the container with public fields, e.g. we want to add the field "noSheets" to our workbook, then this field would not be visible from a template. We support such fields by mapping them into the map's contents. The Java Map implementation is overridden to do so. Now all access from the template engine is done via the map interface, be it access of predefined fields like our example "noSheets" or be it access of true, dynamic contents, i.e. data items like "mySheetA" or "mySheetB". We call the predefined fields "pseudo-fields" since from a template they look like and behave like true public fields of the Java object but in fact they are implemented as map content items.

  This class implements a map, which supports true map behavior (dynamic data items from the application input) and having predefined pseudo-fields (predefined by our application design), that are merged into the map contents. Some generic pseudo-fields are already defined by this base class (e.g. the name of the container) and it provides the mechanisms to let a derived class define its own, further pseudo-fields.

  Two problems arise.

  Evidently, pseudo-fields and true, dynamic data contents share the map key space. All keys are Java String objects with the meaning name-of-object. The name under which a pseudo-field is stored and accessed cannot be used for a dynamic data item at the same time. Since we have the pseudo-field "name_" there can't be a worksheet called `name_` in the workbook `myBook` in our example above. From a template `<myBook.name_>` refers to the name of `myBook` but not to a worksheet of that name.

  The implementation of this map class checks for name clashes of this kind at parse time, when the map is filled with the information from the application input.

  It is impossible to complete parsing if there's such a name clash. Since naming of data items can be controlled via command line options this will not mean that it would be impossible to successfully read the input, only some fine tuning of the application configuration will be required.

  In practice, name clashes will occur only exceptional. Typical names of pseudo-fields in the data model will not likely appear in natural Excel input. Where this is not the case we decided to rename our pseudo-fields, even if this leads to less neat template code. The most prominent example is the name of an object. In the conventional data model this is the public field `name`. Since "name" can easily appear in natural input we called the pseudo-field "name_". The same happens for the index-in-collection, our conventional "i" and "i0" became "i_" and "i0_", respectively.

  The second problem is the documentation. Conventional data models, which are predefined, nested Java classes are appropriately documented with Javadoc. All public fields are listed and explained in meaningful HTML representation and their nesting is easily understandable. Using this container class the pseudo-fields are implemented by run-time code and won't appear as such in the Javadoc documentation.

  At several points the design of the implementation of this map class was driven by considerations how to make information important to StringTemplate V4 template writers visible in the Javadoc documentation. First of all, the pseudo-fields are held in true fields. These are inaccessible via the template engine and not required by surrounding Java code. Under normal circumstances these fields would be implemented private. We made them public so that the application user will find them in Javadoc. The user sees these fields as public - and can indeed access them (if not as public fields but via the map interface as pseudo-field). Secondary, all pseudo-fields are listed as a Java enumeration. For this base class and for each derived container class you will find the related enumeration and each named value will be documented with a short explanation of the pseudo-field it relates to. See e.g. `Cluster.PseudoFieldName` or `ObjectMap.PseudoFieldName`.

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `ObjectMap.PseudoFieldName` This is the list of pseudo-fields of class `ObjectMap` that can be accessed from a StringTemplate V4 template.

    - ### Nested classes/interfaces inherited from class java.util.AbstractMap

      `java.util.AbstractMap.SimpleEntry<K,V>, java.util.AbstractMap.SimpleImmutableEntry<K,V>`

    - ### Nested classes/interfaces inherited from interface java.util.Map

      `java.util.Map.Entry<K,V>`

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `boolean` | `exists` The presence of a container object as Boolean.
    `int` | `i_` The one based index of the object in a collection of those.
    `int` | `i0_` The null based index of the object in a collection of those.
    `ObjectList<T>` | `itemAry` All real data items (in contrast to the pseudo-fields), which are held in the map `itemMap` are stored a second time in this list.
    `java.util.Map<java.lang.String,T>` | `itemMap` This is an embedded map, which stores all real data items (in contrast to the pseudo-fields).
    `Identifier` | `name_` The name of the object.
    `int` | `objId` The ID of this object.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `boolean` | `containsKey(java.lang.Object key)` Check for presence of a given key,value pair in the map.
    `static <T> SortOrder.Comparator<ObjectMap<T>>` | `createComparator(SortOrder.Order sortOrder)` A comparator for sorting containers in a Java List is created and returned.
    `java.util.Set<java.util.Map.Entry<java.lang.Object,java.lang.Object>>` | `entrySet()` Deriving a new Map class from AbstractMap requires at minimum overloading the entrySet function.
    `java.lang.Object` | `get(java.lang.Object key)` Get an object from the Map as it is seen by the StringTemplate V4 engine.
    `int` | `getNoItems()` The number of data items in `itemAry` and `itemMap`.
    `java.lang.Object` | `put(java.lang.Object key, java.lang.Object value)` Adding a real data item to this map object must only be done using `putItem(java.lang.String, T)`.
    `boolean` | `putItem(java.lang.String objectName, T object)` Add a real data item to the map.
    `void` | `setIndexInCollection(int i0)` Set the index-in-collection.
    `java.lang.String` | `toString()` Get the string representation of the map object; it's its name as an identifier.

    - ### Methods inherited from class java.util.AbstractMap

      `clear, containsValue, equals, hashCode, isEmpty, keySet, putAll, remove, size, values`

    - ### Methods inherited from class java.lang.Object

      `getClass, notify, notifyAll, wait, wait, wait`

    - ### Methods inherited from interface java.util.Map

      `compute, computeIfAbsent, computeIfPresent, forEach, getOrDefault, merge, putIfAbsent, remove, replace, replace, replaceAll`

- - ### Field Detail

    - #### objId

          public final int objId

      The ID of this object. Each object in the data model gets a unique ID, which can be useful for having related data objects in the generated code with individual names.

    - #### name_

          public Identifier name_

      The name of the object.
      Remark:
        The name is stored as an object of type `Identifier`. If is is rendered like `<obj.name_>` in a StringTemplate V4 template you will not get the given name but the C identifier, which is most similar to the given name - this can even be identical to the name. If you really want to get the given name then you'd rather put `<obj.name_.givenName>` into your template.

        For consistency, this field would be better named "name" (compare to other elements of the data model). However, all public field names of this class are reserved key words at the same time and can't be used as designations in the application input. Therefore, we can't apply such a common designation as "name".

    - #### i0_

          public int i0_

      The null based index of the object in a collection of those. If the object is held in more than one collection then the index relates to the most important one. The index can be used to support the implementation of arrays or enumerations of objects in the generated output.

      Remark:
        This field should be named `i0` for consistency with our usual data model naming scheme. However, all public field names of this class are reserved key words at the same time and can't be used as designations in the application input. Therefore, we can't apply such a common designation as "i0".

    - #### i_

          public int i_

      The one based index of the object in a collection of those. If the object is held in more than one collection then the index relates to the most important one. The index can be used to support the implementation of arrays or enumerations of objects in the generated output.

      The value of this index is `i0_ + 1`.

      Remark:
        This field should be named `i` for consistency with our usual data model naming scheme. However, all public field names of this class are reserved key words at the same time and can't be used as designations in the application input. Therefore, we can't apply such a common designation as "i"

    - #### itemMap

          public final java.util.Map<java.lang.String,T> itemMap

      This is an embedded map, which stores all real data items (in contrast to the pseudo-fields). Which are the real data items depends on the actual container. This is the base class implementation and different derived conatiner classes will typically contain different kinds of data items:

      - `Cluster`: Data items are `ExcelWorkbook` objects
      - `ExcelWorkbook`: Data items are `ExcelWorksheet` objects
      - `ExcelWorksheet`: Data items are `RowObjectContainer` objects, the groups of row objects
      - `RowObjectContainer`: Recursively contains data items of same type. This model the recursive grouping of row objects
      - `RowObject`: Data items are `CellObject` objects

    - #### itemAry

          public ObjectList<T> itemAry

      All real data items (in contrast to the pseudo-fields), which are held in the map `itemMap` are stored a second time in this list.
      Remark:
        The list is sorted; which order is determined by the application configuration and is kept for reference in `ObjectList.sortOrder`. From a StringTemplate V4 template the sort order can be queried with an expression like `<obj.itemAry.sortOrder>`.

    - #### exists

          public final boolean exists

      The presence of a container object as Boolean. From a StringTemplate V4 template it is a bit tricky to query the existance of a container of this class. While the existance of an object in the data model is normally queried by a template expression like

      `<if(cluster.object)>"object" is present<endif>`

      will this fail for Java Map objects. `<if(cluster.mapObject)>` will return `false` even if the map object exists but if it is empty. Empty maps are however quite common in our data model. Let's take for example a flat worksheet "mySheet" of workbook "myBook" that owns all row objects in the root level and doesn't have nested sub-groups of row objects. The template expression

      `<if(myBook.mySheet)><myBook.mySheet.rowAry:renderRow()><endif>`

      would fail and not render any row object. (Since the map `mySheet` is empty.) Using the flag `exists` the template can be formulated meaningful and safe:

      `<if(myBook.mySheet.exists)><myBook.mySheet.rowAry:renderRow()><endif>`

      See Also:
        Constant Field Values

  - ### Method Detail

    - #### getNoItems

          public int getNoItems()

      The number of data items in `itemAry` and `itemMap`. From a StringTemplate V4 template this member is accessed as `<obj.noItems>`.

    - #### setIndexInCollection

          public void setIndexInCollection(int i0)

      Set the index-in-collection.
      Parameters:
        `i0` - The new value for the null based index of this object in an embedding collection.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### entrySet

          public java.util.Set<java.util.Map.Entry<java.lang.Object,java.lang.Object>> entrySet()

      Deriving a new Map class from AbstractMap requires at minimum overloading the entrySet function. The StringTemplate V4 engine will call this method if the template iterates through the map.

      We overload this method to filter out the pseudo fields, we want to hide when an iteration along all map entries takes place. Filtering the pseudo fields here is a contradictory behavior with the overloaded get method, which will return the pseudo fields. Theoretically, this contradiction could be recognized by the StringTemplate V4 engine but by experience it doesn't complain about.

      Specified by:
        `entrySet` in interface `java.util.Map<java.lang.Object,java.lang.Object>`
      Specified by:
        `entrySet` in class `java.util.AbstractMap<java.lang.Object,java.lang.Object>`
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### containsKey

          public boolean containsKey(java.lang.Object key)

      Check for presence of a given key,value pair in the map.

      The StringTemplate V4 engine will use this Map method prior to the query for the value. We say "is available" to both, contained real data items and pseudo fields. This is a contradictory behavior with the behavior of method entrySet, which won't list the pseudo fields. Theoretically, the contradiction could be recognized by the StringTemplate V4 engine but by experience it doesn't complain about.

      There's a pit-fall: The template engine has a two step approach to find the map entries. First, it tries to identify the entry by passing in the template attribute, which is used in the template map operator `.()`. The attribute is represented in the StringTemplate defined Java class; different template constructs will yield different Java classes. If the engine gets a negative response then it tries again, this time with the attribute rendered as text, as a Java String object. (If the internal attribute representation already is a Java String then no second attempt is made.)

      For us, it's impossible to operate on the internal StringTemplate classes. Therefore we reject all queries with key objects, which are not of Java class String and wait for the second attempt.

      Specified by:
        `containsKey` in interface `java.util.Map<java.lang.Object,java.lang.Object>`
      Overrides:
        `containsKey` in class `java.util.AbstractMap<java.lang.Object,java.lang.Object>`
      Parameters:
        `key` - The key attribute from the template.
      Returns:
        `true` for contained real data items and pseudo fields if referenced to by Java String keys, `false` otherwise.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### get

          public java.lang.Object get(java.lang.Object key)

      Get an object from the Map as it is seen by the StringTemplate V4 engine. The object can either be a pseudo-field or a real data item.
      Specified by:
        `get` in interface `java.util.Map<java.lang.Object,java.lang.Object>`
      Overrides:
        `get` in class `java.util.AbstractMap<java.lang.Object,java.lang.Object>`
      Parameters:
        `key` - The key, which the demanded object is associated with. In practice and due to the behavior of the StringTemplate V4 engine this will always be a Java String. This type is ensured by assertion. See method `containsKey(java.lang.Object)`, too.
      Returns:
        Get the object or null if no such object exists.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### put

          public java.lang.Object put(java.lang.Object key,
                                      java.lang.Object value)

      Adding a real data item to this map object must only be done using `putItem(java.lang.String, T)`. Java's `Map.put(K, V)` is overridden only to double-check this by assertion.
      Specified by:
        `put` in interface `java.util.Map<java.lang.Object,java.lang.Object>`
      Overrides:
        `put` in class `java.util.AbstractMap<java.lang.Object,java.lang.Object>`
      Parameters:
        `key` - The name of the object.
        `value` - The added object of template type .
      Returns:
        Always returns null. But will always fire an assertion before.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### putItem

          public boolean putItem(java.lang.String objectName,
                                 T object)

      Add a real data item to the map.
      Parameters:
        `objectName` - This is the name under which the object is stored in the map. Must not be null.
        `object` - The object to add. Must not be null.
      Returns:
        Get the Boolean information whether the object could be added to the map. Adding can fail if the object's name clashes with a reserved keyword or an already contained object.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.

    - #### createComparator

          public static <T> SortOrder.Comparator<ObjectMap<T>> createComparator(SortOrder.Order sortOrder)

      A comparator for sorting containers in a Java List is created and returned.
      Parameters:
        `sortOrder` - The wanted sort order. Sorting is done with respect to the name `name_` of the container. Sorting is done based on `SortOrder.createComparatorString(excelExporter.excelParser.SortOrder.Order)`; refer to this method to get details about the behavior of sorting.
      Returns:
        Get the temporary comparator object as usable with the Java Collections class.

    - #### toString

          public java.lang.String toString()

      Get the string representation of the map object; it's its name as an identifier. From a StringTemplate V4 template this representation of the object is not accessible. Here you need to reference the object's name, e.g. `<obj.name_>`.
      Overrides:
        `toString` in class `java.util.AbstractMap<java.lang.Object,java.lang.Object>`
      Returns:
        Get the string value.
      Remark:
        This method is irrelevant and meaningless to a StringTemplate V4 template.