MAP | PageMixer Documents > Tutorial > Mixing with PageMixer > Iterate sub-sequence | << | >> |
This section explains
how to iterate part of HTML page
in PageMixer framework.
For this purpose,
this section uses "shopping basket" example and
the filter
iterate and inset data into part
between "<tr>
" and
corresponding "</tr>
" in HTML page.
<table class="basket"> <tr class="Shop-Basket-Entry"> <td> <span class="Shop-Basket-EntryName">(Name)</span> </td> <td> <span class="Shop-Basket-EntryPrice">(Price)</span> </td> <td> <input type="text" class="Shop-Basket-EntryCount" name="xxx" value="0"> </td> <td> <span class="Shop-Basket-EntryTotal">(Sub total)</span> </td> </tr> </tabl>
<table class="basket"> <tr class="Shop-Basket-Entry"> <td> <span class="Shop-Basket-EntryName">banana</span> </td> <td> <span class="Shop-Basket-EntryPrice">120</span> </td> <td> <input type="text" class="Shop-Basket-EntryCount" name="Shop.Basket.Entry.ID:i0001" value="1"> </td> <td> <span class="Shop-Basket-EntryTotal">120</span> </td> </tr> <tr class="Shop-Basket-Entry"> <td> <span class="Shop-Basket-EntryName">broccoli</span> </td> <td> <span class="Shop-Basket-EntryPrice">165</span> </td> <td> <input type="text" class="Shop-Basket-EntryCount" name="Shop.Basket.Entry.ID:i0002" value="2"> </td> <td> <span class="Shop-Basket-EntryTotal">330</span> </td> </tr> : : </table>
Class diagram in this section is shown below:
Classes which you must define are colored, and other are already defined.
Object diagram in this section is shown below:
Sequence diagrams in this section are shown below:
First diagram is one until filter detects sub-sequence to be iterated.
And second is one after getting iterator from
DataProvider
.
In this tutorial, abbreviated class names are used. Complete names are shown below.
Notation | Full name |
---|---|
ConsumerContext | jp.ne.dti.lares.foozy.pagemixer.mixer.ConsumerContext |
DataProvider | jp.ne.dti.lares.foozy.pagemixer.mixer.DataProvider |
HTMLSymbolSet | jp.ne.dti.lares.foozy.pagemixer.HTMLSymbolSet |
ListDataProvider | jp.ne.dti.lares.foozy.pagemixer.mixer.ListDataProvider |
SequenceDataIterationFilter | jp.ne.dti.lares.foozy.pagemixer.mixer.SequenceDataIterationFilter |
SequenceWatcher | jp.ne.dti.lares.foozy.pagemixer.mixer.SequenceWatcher |
Notation | Full name |
---|---|
BasketEntry | common.BasketEntry |
BasketEntryIterationFilter | pagemixer.filter.BasketEntryIterationFilter |
Bootstrap | pagemixer.filter.Bootstrap |
EntryCountAttr | pagemixer.filter.BasketEntryIterationFilter.EntryCountAttr |
EntryNameText | pagemixer.filter.BasketEntryIterationFilter.EntryNameText |
EntryPriceText | pagemixer.filter.BasketEntryIterationFilter.EntryPriceText |
EntryTotalText | pagemixer.filter.BasketEntryIterationFilter.EntryTotalText |
This section iterates part of HTML page for instance collection of below class.
public class BasketEntry { // "ShoppingItem" contains ID, name, price of item. final private ShoppingItem item_; private int count_; //////////////////////////////////////// public BasketEntry(ShoppingItem item, int count){ item_ = item; count_ = count; } //////////////////////////////////////// public String getID(){ return item_.getID(); } public String getName(){ return item_.getName(); } public String getName(Locale locale){ return item_.getName(locale); } public int getPrice(){ return item_.getPrice(); } public void setCount(int count){ count_ = count; } public int getCount(){ return count_; } }
DataProvider
To iterate part of HTML page, data collection provider is needed. Given collection can tell how many times it should repeat, and what data is should be inset.
PageMixer framework generalizes what provides collection of data
as "DataProvider
".
It is interface,
and hides implementation of data holding.
It defines only one method as below.
public interface DataProvider { public java.util.Iterator provide(); }
"provide()
" returns java.util.Iterator
,
which is of data collection.
You can get Iterator
of it
by invoking DataProvider#provide
always
when you need it.
In this example,
DataProvider
which provides
collection of BasketEntry
is created as below.
// "entryList" as java.util.List // contains "BasketEntry"s ListDataProvider provider = new ListDataProvider(entryList);
"ListDataProvider
" is implementation class
of DataProvider
with java.util.List
.
Of course,
you can define "shopping basket" class,
which holds BasketEntry
objects,
as implementation class of interface DataProvider
.
NOTE:
You do not have to create DataProvider
,
if you override getIterator(Object)
of
SequenceDataIterationFilter
.
This allow you to get Iterator
from
your specific object directly.
DataProvider
To identify DataProvider
and data to be inset,
SequenceDataIterationFilter
requires
two keys like below:
Object providerKey = "Shop.Basket.BasketEntryProvider"; Object dataKey = "Shop.Basket.BasketEntry";
"providerKey
" identifies
DataProvider
,
and "dataKey
" identifies
data, which may be BasketEntry
object.
In this section,
"SequenceDataIterationFilter
" is used as main filter,
but the only thing
which SequenceDataIterationFilter
affects
to Token sequence directly
is to iterate part of Token sub-sequence.
It does not inset data into iterated Token sub-sequence by itself.
Instead of doing so,
it delegates responsibility to do so
to co-operatvie other filters.
This separation makes SequenceDataIterationFilter
simple and re-usable.
SequenceDataIterationFilter#push(Filter)
is used
to register co-operative filter,
and registered one is used only
to inset data into iterated sub-sequence.
Below filters may be needed for "shopping basket" example.
<input>
"
In fact, these filters are defined as inner class of sample filter class in this section. Each of these are so simple and easy to understand with knowledge of former sections that this section omits explanation of them. Please see source files directly for detail.
SequenceWatcher
As described above,
this section let the filter
iterate part
between "<tr>
" and
corresponding "</tr>
" in HTML page.
But, it is not good idea to repeat all parts
between them in given HTML page.
Then, condition of target sub-sequence are:
tr
"
class
" attribute, and
Shop-Basket-Entry
"
In this case,
"SequenceWatcher.NameAttr
" is used
as "SequenceWatcher
".
It is "Sequence Watcher watching at Name and Attribute of first token".
new SequenceWatcher.NameAttr(HTMLSymbolSet.SET.TR, HTMLSymbolSet.SET.CLASS, "Shop-Basket-Entry")
SequenceDataIterationFilter
Sample filter class of this section is defined as below.
public class BasketEntryIterationFilter extends SequenceDataIterationFilter { final static private HTMLSymbolSet SET = HTMLSymbolSet.SET; final static private String VALUE = "Shop-Basket-Entry"; //////////////////////////////////////// public BasketEntryIterationFilter(Object providerKey, Object dataKey) { super(new SequenceWatcher.NameAttr(SET.TR, SET.CLASS, VALUE), providerKey, dataKey); push(new EntryNameText(dataKey)); push(new EntryPriceText(dataKey)); push(new EntryCountAttr(dataKey)); push(new EntryTotalText(dataKey)); } }
Classes of push
ed instance in constructor
are of co-operative filters.
Now, everything needed are ready to use. Execution code is as below (see BasketEntryIterationFilter for detail).
try{ // key to set/get DataProvider final Object providerkey = "Shop.Basket.BasketEntryProvider"; // key to set/get provided data final Object dataKey = "Shop.Basket.BasketEntry"; Bootstrap bootstrap = new Bootstrap.Default(filename) { protected void prepare(ConsumerContext context) { List entryList = BasketEntry.getEntryList(); ListDataProvider provider = new ListDataProvider(entryList); // put DataProvider into context context.setValue(providerKey, provider); } }; BasketEntryIterationFilter filter = new BasketEntryIterationFilter(providerKey, dataKey); // apply the filter bootstrap.execute(filter); } catch(Exception e){ e.printStackTrace(System.err); }
Sample HTML file as input is "basket.en.html
"
under "src/demo/servlet/war/WEB-INF/page/demosite
"
in distribution.
You can see some(determined by random number) entries of "shopping basket" in result HTML page of above execution code.
MAP | PageMixer Documents > Tutorial > Mixing with PageMixer > Iterate sub-sequence | << | >> |