[stringtemplate-interest] Problems with List and Hashes revisited

Dreyer Ulf (CR/APA3) Ulf.Dreyer at de.bosch.com
Mon May 29 06:55:46 PDT 2006


Hello all!

I hope, I'm not getting on your nerves yet but I'd like to
diskuss my issue with ST# some more.
First let me quote Jeremy (who put it so nicely)
"At the end of the day I absolutely love ST#"

But at times it is driving me up the wall!
(Or maybe it is my ignorance about some finer points
of ST#)

I am trying to read (more or less arbitrary) xml data
from disc and feed them to a 'root template' which
in turn calls other user-defined subtemplates.

As my mail is rather long (again) the problem in short:
I think (not entirely sure) ST# somtimes treats single
values (which are aggregates (hashmap)) as lists. 
(It enumerates my hash)
"Sometimes" meaning whenever I call a subtemplate
that is defined without formal parameters OR
I call a subtemplate (with or without formal parameters defined)
in the   <single value>:subtemplate() syntax.
??
What do I have to do so that ST# can deal with
<DataStruct>:subtemplate()
whether DataStruct is a single value (or aggregate)
or a List?
??
Putting another pair of brackets "()" around the argument
does'nt work because 
a) it is not universal (if the argument CAN be multi-valued)
b) it casts the argument to string (which is bad for aggregate values)


First some real code so you have a chance to 
understand, what I am talking about:
(sorry for the lengthy text but I hope it helps)

Sample xml-file:

<?xml version="1.0"?>
<root>
    <DataBlock1>
		<DataA>1_DataA</DataA>
		<DataB>1_DataB</DataB>
		<DataC>
			<SubC1>1_SubC1Content1</SubC1>
			<SubC1>1_SubC1Content2</SubC1>
			<SubC2>1_SubC2Content</SubC2>
		</DataC>
    </DataBlock1>
	<DataBlock1>
		<DataA>2_DataA</DataA>
		<DataB>2_DataB</DataB>
		<DataC>
			<SubC1>2_SubC1Content1</SubC1>
			<SubC1>2_SubC1Content2</SubC1>
			<SubC2>2_SubC2Content</SubC2>
		</DataC>
    </DataBlock1>
	<DataBlock2>
		<ItemB>ItemBContent</ItemB>
	</DataBlock2>
</root>
-------------------------------------------------------------
Sample TemplateGroup:

group behaviourDemo;

subsubTemplate(Data) ::= <<
	Input is : $Data$
	SubC1 is '$Data.SubC1$'
	SubC2 is '$Data.SubC2$'

>>

subsubTemplateB() ::= <<
	Input is : $it$
	SubC1 is '$it.SubC1$'
	SubC2 is '$it.SubC2$'

>>

subTemplate() ::= <<
------------------------------------------------------
A=$it.DataA$
B=$it.DataB$

// both blocks SHOULD return the same:

subsubTemplate(it.DataC):
$subsubTemplate(it.DataC)$
----------------------------
it.DataC:subsubTemplate():
$it.DataC:subsubTemplate()$
------------------------------------------------------

>>

rootTemplate(DataBlock1,DataBlock2) ::= <<
BEGIN (rootTemplate)
 Applying the subtemplate to DataBlock1:

$DataBlock1:subTemplate()$
======================================================
 Accessing part of DataBlock1 directly (multi-valued):
DataBlock1.DataA = $DataBlock1.DataA$

 Accessing part of DataBlock2 directly (single-valued):
DataBlock2.ItemB = $DataBlock2.ItemB$
END (rootTemplate)
>>

To archive my goal I have written a data-structure consisting
of ArrayLists and Hashmaps (alternating).
A hash being the root and containing Lists(of hashes) for multi-valued
attributes or attributes (Strings) for single-values.

DataBlock2.ItemB = $DataBlock2.ItemB$ from the rootTemplate always
works. (good!)

DataBlock1.DataA = $DataBlock1.DataA$ does not normally work because the
"answer" 
would be multi-valued.
I got this to work too by writing a List which implements a this[string]
accessor that
iterates over the list and constructs a new list from the matching
attributes of the
hashmaps in the list. (Essentially skipping one "layer" of the data
structure)
@Kunle: This is how I solved the last problem I mailed you about.
In the example my list implementation returns [1_DataA,2_DataA] if
called as
myList_DataBlock1["DataA"] (Not necessarily stings but whatever the
hashes contain at key "DataA").


One last problem which I feel is related to the " question regarding
specialcasingof IList"
previously on the mailinlist.
The call to the subsubTemplate!

As you see from the code I have given two implementations.
The one with the named parameter works IF (and only if) I call it
$subsubTemplate(it.DataC)$
My preferred version of
$it.DataC:subsubTemplate()$
does NOT work.
Neither does the subsubTemplateB in any version

>From the output below one can see that $it.DataC:subsubTemplate()$
gives a list to subsubTemplate() when it SHOULD be a Hash containing
a list (of 2 items) and a single value.
Any idea why this is the case?
My implementations of of List and Hash:

public class AttributeList : ArrayList,Iattribute
public class AttributeHash : IDictionary, IAttribute

(Iattribute defines  object this[object key] but it
does not work without this hack in AttributeList either)
------------------------------------------------------
BEGIN (rootTemplate)
 Applying the subtemplate to DataBlock1:

------------------------------------------------------
A=1_DataA
B=1_DataB

// both blocks SHOULD return the same:

subsubTemplate(it.DataC):
        Input is : 1_SubC1Content11_SubC1Content21_SubC2Content
        SubC1 is '1_SubC1Content11_SubC1Content2'
        SubC2 is '1_SubC2Content'

----------------------------
it.DataC:subsubTemplate():
        Input is : 1_SubC1Content11_SubC1Content2
        SubC1 is ''
        SubC2 is ''
        Input is : 1_SubC2Content
        SubC1 is ''
        SubC2 is ''

------------------------------------------------------
------------------------------------------------------
A=2_DataA
B=2_DataB

// both blocks SHOULD return the same:

subsubTemplate(it.DataC):
        Input is : 2_SubC1Content12_SubC1Content22_SubC2Content
        SubC1 is '2_SubC1Content12_SubC1Content2'
        SubC2 is '2_SubC2Content'

----------------------------
it.DataC:subsubTemplate():
        Input is : 2_SubC1Content12_SubC1Content2
        SubC1 is ''
        SubC2 is ''
        Input is : 2_SubC2Content
        SubC1 is ''
        SubC2 is ''

------------------------------------------------------

======================================================
 Accessing part of DataBlock1 directly (multi-valued):
DataBlock1.DataA = 1_DataA2_DataA

 Accessing part of DataBlock2 directly (single-valued):
DataBlock2.ItemB = ItemBContent
END (rootTemplate)
-------------------------------------------------------

Before that I get some errors along the lines of

Can't get property SubC1 via C# string indexer from
SomeNameSpace.AttributeList instance
[...]
Class System.String has no such attribute: SubC2 in template context
[rootTemplate subTemplate subsubTemplate]

Where SomeNameSpace.AttributeList is my Listimplementations which
supports attribute lookup from
the listed hashes.

I don't understand why ST# tries to get the attribute from a string.

Has anyone similar problems or any idea how I can get the expected
results from ST?
@ Terrence or Kunle: how does the Attribute-Lookup work exactly?


Thanks for reading this far!

Ulf


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20060529/7cf6133d/attachment-0001.html


More information about the stringtemplate-interest mailing list