How to get "@Prefix" value from an Place.Tokenizer? or how to set via clientbundle constants?

342 views
Skip to first unread message

tanteanni

unread,
Oct 24, 2011, 5:14:54 AM10/24/11
to google-we...@googlegroups.com
My app uses activities and places. All my places' tokenizers have "prefixes" to make bookmarks more readable. instead of calling PlaceController.goTo(new Place) i often use (inline)hyperlinks that point to another place or state - i think it is more readable and transparent for the user. The problem is: on generating /building those links i need the prefix of the respective place, at the moment those classes have a string constant with the prefix' value - a bad thing, will break as soon as someone changes the prefix.

at the moment i see two ways to get rid of the "magic" string constants in the link-building class:
- let the place implement a "getInlineLink()" - Method(probably specified within an interface), the prefix is to be set as an static constant within the place
- get the prefix somehow - is there a way to get the value of prefix of a place'tokenizer class?
- provide the strings via client bundle constants interface
- another way or is this all bullshit ?

so what do you suggest?

thx in advance

Jens

unread,
Oct 24, 2011, 5:43:14 AM10/24/11
to google-we...@googlegroups.com
You can use:

AppPlaceHistoryMapper mapper = ... //get mapper somehow
myHyperLink.setTargetHistoryToken(mapper.getToken(new MyPlace(stateVar1, stateVar2, ...)));

-- J.

tanteanni

unread,
Oct 24, 2011, 8:15:22 AM10/24/11
to google-we...@googlegroups.com
thx!

that is exactly what i am looking for.

tanteanni

unread,
Oct 26, 2011, 3:18:16 AM10/26/11
to google-we...@googlegroups.com
i have one problem with this solution: testability
since i generate those links in an activity i want test it without GwtTestCase. But using my AppPlaceHistoryMapper smells like the need for GWTTestCase?!

i think i will refactor my code and give the place a string constant (public or with getter) and use this as prefix - good idea?

Jens

unread,
Oct 26, 2011, 4:35:52 AM10/26/11
to google-we...@googlegroups.com
Oh yes I think you will need a GWTTestCase as the mapper is created with GWT.create(). I did not had that in mind because I have implemented PlaceHistoryMapper myself (nicer url scheme) so there is no need for GWT.create().


Thomas Broyer

unread,
Oct 26, 2011, 9:07:36 AM10/26/11
to google-we...@googlegroups.com
Isn't that what mocks are for?

tanteanni

unread,
Oct 26, 2011, 9:51:12 AM10/26/11
to google-we...@googlegroups.com
i guess you mean to implement my own PlaceHistoryMapper - only for test?

that could work

but now i am happy with my getPrefix() in place-class. With this i don't need a dependency to historymapper in my activity. (it don't feels right to use historymapper to get a constant string from a place?!)

Thomas Broyer

unread,
Oct 26, 2011, 10:03:27 AM10/26/11
to google-we...@googlegroups.com


On Wednesday, October 26, 2011 3:51:12 PM UTC+2, tanteanni wrote:
i guess you mean to implement my own PlaceHistoryMapper - only for test?

that could work

Yes, with the added benefit that you could test whether you call the PlaceHistoryMapper with the appropriate argument, not whether the returned value from the place-to-string conversion is the one you expect (which will change when you change your PlaceTokenizer, but you're not testing your PlaceTokenizer here, you're testing your activity, and if the test changes when the implementation of another class changes –without breaking the contract: turn a place into a string–, it's no longer a *unit* test; and it also means you'd have to change all your tests when you decide to change what your PlaceTokenizer generates/parses).
With a mock, the exact output wouldn't matter, the input would however: does my activity calls the mapper with the appropriate argument?
 
but now i am happy with my getPrefix() in place-class. With this i don't need a dependency to historymapper in my activity. (it don't feels right to use historymapper to get a constant string from a place?!)

Well, the goal of PlaceHistoryMapper *is* to get a string out of a place (and the reverse). Whether it's used by the PlaceHistoryHandler or your code the builds link doesn't really matter. 

tanteanni

unread,
Oct 26, 2011, 10:13:47 AM10/26/11
to google-we...@googlegroups.com
thx!

once again i learned a lot :-)

tanteanni

unread,
Oct 26, 2011, 10:24:37 AM10/26/11
to google-we...@googlegroups.com
ok some questions remain:

i just "implemented" my AppHistoryMapper. I need one implementation per place, right? (i guess that is what gwt.create does: generating one mapper per place using the tokenizer code for implementation?)
with this mock in place: is the code provided bei jens ("myHyperLink.setTargetHistoryToken(mapper.getToken(new MyPlace(stateVar1, stateVar2, ...)));")) working without gwtTestCase? Which part is "extracting" the prefix from place (some where in setTargetHistoryToken?)?


Jens

unread,
Oct 26, 2011, 11:03:39 AM10/26/11
to google-we...@googlegroups.com
i guess that is what gwt.create does: generating one mapper per place using the tokenizer code for implementation?

Only one mapper is generated. It contains a large generated if-then-else block that delegates getPlace() and getToken() to the correct Tokenizer based on the prefix (use -gen compiler option to see whats generated).

I think you only need one mocked mapper. If you want to test an activity the mocked mapper would do nothing except tracking method calls and its arguments as Thomas said. If your activity has a method "configureLinks()" that you want to test, it only matters that your activity calls mapper.getToken(...<place for each link that has to be configured>...) with the correct places as arguments inside this method. The mapper could also just return specific test strings per place (e.g. "a", "b", "c", ... so no real tokens created by tokenizers) because it only matters that these strings are set to the hyperlinks, it does not matter if theses strings are correctly generated by the mapper.

My code contains a Hyperlink instance so it would not work without GWTTestCase. Its just a short-hand code snippet. In reality you would have a method like updateLinkAToken(String token) in your view interface and the activity would do:

mockedView.updateLinkAToken(mockedMapper.getToken(new Place(....))).

As your mockedView and mockedMapper should not have a dependency to JSNI / GWT.create() it will work without a GWTTestCase.

-- J.
Reply all
Reply to author
Forward
0 new messages