Adding Parameterized Blocks to SBT Files

This page extends the proposed changes to Item Blocks mention in here.

In the current implementation, the contents of an ItemBlock are copied exactly. I proposed extending this to allow for parameterization of the Block so that when it is instantiated, the consumer can specify new content.

Existing Item Blocks

Here is an example of defining and using Item Blocks:

 <ItemBlocks>
    <Block Name="B1">
      <ItemDefinitions>
        <String Name="s1">
          <Categories>
            <Cat>Solid Mechanics</Cat>
          </Categories>
        </String>
        <Int Name="i1">
          <DefaultValue>0</DefaultValue>
        </Int>
      </ItemDefinitions>
    </Block>
  </ItemBlocks>

  <Definitions>
    <AttDef Type="Type0">
      <Categories>
        <Cat>Fluid Flow</Cat>
      </Categories>
      <ItemDefinitions>
        <Double Name="foo"/>
        <Block Name="B1"/>
        <String Name="bar"/>
      </ItemDefinitions>
    </AttDef>
  </Definitions>

The following figure depicts how Item Blocks are currently processed:

The XML attribute reader maintains a global dictionary of exported serialized Item Blocks and are keyed to the Block’s name. When processing a template file, these global blocks converted into XML elements and are prepended to those defined in the local template file. All of these XML elements are then traversed and are used to form a dictionary of XML elements. If we encounter an exported Item Block in the local template file, the element is serialized and added to the Global dictionary.

When a Block is referenced, the name is looked up in the XML Element map and the located element is parsed.

Now let’s assume we want to parameterize the Block so that the default value and label of i1 to be redefined when the Block is referenced. In this case I am proposing that we replace the name Block with the name Template.

 <Templates>
    <Template Name="B1">
      <Parameters>
        <Param Name = "def1"> 0 </Param>
      </Parameters>
      <Contents>
        <ItemDefinitions>
          <String Name="s1">
            <Categories>
              <Cat>Solid Mechanics</Cat>
            </Categories>
          </String>
          <Int Name="i1" Label="IntLabel{def1}">
            <DefaultValue>{def1}</DefaultValue>
          </Int>
        </ItemDefinitions>
      <Contents>
    </Template>
  </Templates>

  <Definitions>
    <AttDef Type="Type0">
      <ItemDefinitions>
        <Template Name="B1">
          <Param Name="def1"> 15 </Param>
        </Template>
      </ItemDefinitions>
    </AttDef>
    <AttDef Type="Type1">
      <ItemDefinitions>
        <Template Name="B1"/>
      </ItemDefinitions>
    </AttDef>
  </Definitions>

In the above example, the Template B1 has a parameter def1 that has a default value of 0. Definition Type0 references B1 with the parameter def1 set to 15, would contain an Int Item Definition i1 with a label named IntLabel15 and has a default value of 15. Definition Type1 is referencing B1 with def1 set to its default value of 0 resulting in its i1 Int Item Definition with a label of IntLabel0 and a default value of 0.

To support such a feature I would propose the following:

In this case I’ve added a data structure called TemplateInfo. TemplateInfo contains a string that represent the XML contents (same as the original Block content) and a map of parameters strings to string values that represent the default parameter values.

The reader will maintain a map of global Template Names to TemplateInfos.

When an new template file is processed, a local map is created from the global map and if the template file contains a Templates XML element, its contents are added to the local map (as well as to the global map if the template is exported).

When a template reference is found, the following is performed:

  • Create a new copy of the referenced template’s parameters and add any parameter mentioned in the template reference.
  • Do a string substitution of all of the parameters in the local copy into the template contents to form a new string that will be deserialized to form an new XML element
  • Process the new XML element

@johnt @dcthomp @Aaron @justin.2.wilson @rohith @aron.helser FYI

+1 on the generalized parameters.

Among other possible features to consider in the future:

  • Conditional logic: insert different text depending on an input parameter. I have some situations where the desired result is different for expressions with 3 variables (xyz) versus 4 (txyz).
  • Array parameters: In my pug templates, I sometimes pass in an array of strings as one parameters, just for convenience (syntactic sugar, as they say).

So I examined how the XML Parsers worked and came up with the following that shows which methods processes which XML Elements:

V1 Parser

  • processDerivedItemDefinition - this calls processValueDef
    • DiscreteInfo
      • Set of Discrete Elements
        • Structure Elements
          • Set of Item Names
          • Categories Element
            • Sets of Inclusion and Exclusion
    • DefaultValue
    • RangeInfo ← Should range info have block support?
  • processValueDef - this calls processItemDef
    • Labels
    • ExpressionType
    • ChildrenDefiniitons
  • processItemDef
    • Categories
    • Description Elements
  • getCategories
    • set of category elements - currently don’t care about the element name
  • process - method explicitly searched for specific elements - would need to be restructured if we wanted to have block support
    • Analyses - set of Analysis Elements
      • Analysis Element - set of category elements
    • AdvanceLevels - set of Advance Level Elements
    • ActiveCategories - set of Category Elements
    • ItemBlocks
    • AssociationRules
    • Definitions
    • Attributes
    • Views
  • processDefinition
    • Color Information elements
    • Description Elements
    • Association Information Element
    • ItemDefiniitons

V2 Parser

  • processDefinition - added RootName attribute
  • added extensible File and Directory items and defs
  • Added extensible MeshEnitity Items
  • Added Secure StringItemDefs
  • New View parsing done in View namespace

V3 Parser

  • process
    • Configurations
    • Associations
  • processDefiniitonInformation
    • Exclusions
    • Prerequisites
  • processDefinition
    • Categories
    • Tags
  • processAssociationDef - replaces V1 Implementation
  • processReferenceIDef - replaces V1 Implementation
    • Accepts
    • Rejects
    • ConditionalInfo

V4

  • process
    • Evaluators
  • processDefiniiton
    • AssociationRule
    • DissasociationRule
  • processItemDef
    • Tags

V5

  • nothing definition related

V6

  • New Category Format

The main issue is that the parsers work by searching for explicit elements in the XML representation and then processing those elements. In order to put in Block support, we need to invert the control logic so that we iterate over all of the XML child elements and pass them into methods that will determine how they should be processed. If the V(X) Parser implementation does not recognized the element type then it is passed to the V(X-1) implementation.

The iteration method would then explicitly look to see if a Block Instantiation Element is encountered, create the appropriate block of XML elements and then recursively call itself with those elements.

I plan on initially doing this for Definition (so that Blocks could be used for Association Information, and for Value Item Definitions so that Blocks can be used for Discrete Information) but this can be expanded later if there is need.