Re: test for default history content

If getTargetStates isn't needed to dereference history states, then it 
can be dropped altogether, because it is returning the same thing as 
transition.target.

- Jim
On 4/2/2014 5:27 AM, Ate Douma wrote:
> On 02-04-14 00:10, Jim Barnett wrote:
>> Ate,
>>     There is a problem if getTargetStates does not dereference 
>> history states.
>> computeEntrySet calls it to produce the initial list of states for
>> addDescendentStatesToEnter to expand.  If getTargetStates doesn't 
>> dereference
>> history states, they will get added to the statesToEnter list before
>> addDescendentStatesToEnter gets called - and history states should 
>> not be on
>> statesToEnter. Furthermore, computeExitSet calls getTargetStates, and 
>> it will
>> also need to know what the actual dereferenced target state set is.
>
> Right. And I realize I already solved this differently, and IMO 
> elegantly, in my implementation :)
>
> The 'hint' leading to my implementation was the fact that 
> addDescendantStatesToEnter (also) stores the state parameter in 
> statesToEnter. And is expected to do so as it recursively is invoked 
> for derived states which were not yet initially added to the 
> statesToEnter.
>
> What I thus did instead is the following (in pseudo language):
>
>   procedure computeEntrySet(transitions, statesToEnter, 
> statesForDefaultEntry)
>      enterableTargets = new OrderedSet()
>      historyTargets = new OrderedSet()
>      for t in transitions:
>          for s in getTargetState(t.target)):
>           if isHistoryState(s):
>             historyTargets.add(s)
>           else
>             enterableTargets.add(s)
>      for s in enterableTargets:
> addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry)
>      for h in historyTargets:
> addDescendantStatesToEnter(h,statesToEnter,statesForDefaultEntry)
>      // unmodified below
>      for t in transitions:
>           ancestor = getTransitionDomain(t)
>           for s in getTargetStates(t.target)):
>               addAncestorStatesToEnter(s, ancestor, statesToEnter, 
> statesForDefaultEntry)
>
> This way, no history state is added to enterableStates because 
> addDescendantStatesToEnter only does this for non-history states.
>
> Note that addAncestorStatesToEnter will work just fine with a history 
> state as parameter.
>
> Finally, concerning computeExitSet: this also isn't a problem in my 
> implementation because I already 'compile' the source of a history 
> transition to that of its parent state, and actually (thus) can 
> 'compile' the transitionDomain and the targets of a transition at 
> document load time.
>
> In pseudo-language in the algorithm, this also can easily be catered 
> for if you update getTransitionDomain as follows:
>
>   function getTransitionDomain(t)
>     tstates = getTargetStates(t.target)
>     if not tstates
>         return t.source
>     state = t.source
>     if isHistoryState(t.source):
>       state = t.source.parent
>     if t.type == "internal" and isCompoundState(state) and 
> tstates.every(lambda s: isDescendant(s,state)):
>         return state
>     else:
>         return findLCCA([state].append(tstates))
>
> The above can further be optimized by filtering out the history 
> targets from being passed to the lambda expression or from the 
> findLCCA(stateList), but it isn't necessary either.
>
> With the above minor improvements, the getTargets(transition) as well 
> as the getTransitionDomain(transition) procedures can remain 
> 'stateless' (not history state aware) and can be compiled at load time.
> If you add history dereferencing to getTargets(transition) this no 
> longer will be possible, so IMO is something we should try not to do.
>
>>
>> It's a big gap in the algorithm that getTargetStates isn't defined - I'm
>> assuming that it was in an earlier version, and got lost somewhere.
>>
>> In any case we need multiple fixes so that: 1) history states don't 
>> end up on
>> the statesToEnter list and 2) default history executable content gets 
>> recorded.
>
> See my above proposed changes, AFAICT it solves 1) elegantly and then 
> 2) no longer is an issue (already solved by the earlier update to the 
> algorithm).
>
> Regards,
> Ate
>
>>
>> - Jim
>> On 4/1/2014 2:45 PM, Ate Douma wrote:
>>> On 29-03-14 20:26, Zjnue Brzavi wrote:
>>>> On Sat, Mar 29, 2014 at 1:24 PM, Jim Barnett <1jhbarnett@gmail.com
>>>> <mailto:1jhbarnett@gmail.com>> wrote:
>>>>
>>>>     Zjnue,
>>>>       I agree that we need more tests, but why would 
>>>> defaultHistoryContent need
>>>>     to get passed to getTargetStates?  It's just an accessor 
>>>> function.  Though I
>>>>     do think we have to consider how getTransitionDomain and 
>>>> findLCCA should
>>>>     handle history states. They ignore them at the moment, and 
>>>> _maybe_ that's
>>>> ok...
>>>>
>>>>     - Jim
>>>>
>>>>
>>>> Hi Jim,
>>>>
>>>> Perhaps as quick background, my implementation follows (atm) the 
>>>> proposed
>>>> algorithm pretty much verbatim, in order to aid debugging for cases 
>>>> like this
>>>> and to make getting started with SCXML a little easier for myself 
>>>> and others.
>>>>
>>>> Simply put, the recently published changes to the algorithm for
>>>> defaultHistoryContent support are not satisfying test579.
>>>>
>>>> While the getTargetStates function seems pretty harmless, it is also
>>>> hisory-aware and can redirect a transition target.
>>>
>>> Hi Zjnue,
>>>
>>> Sorry for chiming in this late, and going back to this earlier 
>>> message, but
>>> I'm puzzled by the above statement.
>>>
>>> I can find no indication in the algorithm nor in the specification 
>>> text that
>>> the getTargetStates function is supposed to do anything more than just
>>> returning the direct target(s) of a transition.
>>>
>>> It seems to me that the problems you encountered are actually 
>>> *caused* by the
>>> the history-awareness and dereferencing in your getTargetStates 
>>> implementation.
>>>
>>> AFAICT the pseudo algorithm expects it will take care of the history
>>> dereferencing itself in the addDescendantStatesToEnter procedure.
>>> If you do this upfront in you getTargetStates implementation, the
>>> addDescendantStatesToEnter never will get to 'see' a history state 
>>> as it is
>>> supposed to, and neither can it then handle the default history 
>>> content as
>>> just was added.
>>>
>>> I just completed the implementation of the current algorithm for Apache
>>> Commons SCXML (although not yet committed), and I now can 
>>> successfully run
>>> test579, so it seems to me the proposed change simply works as 
>>> expected.
>>>
>>> But maybe I'm overlooking some other specification requirements for
>>> getTargetStates?
>>> I'd appreciate some pointers in that case :)
>>>
>>> Regards, Ate
>>>
>>>
>>>> In the case of test579, the <initial> transition, targets <history 
>>>> id="sh1">,
>>>> but is effectively redirected to <state id="s01" >, skipping any 
>>>> executable
>>>> content of <history> along the way.
>>>>
>>>> Please take a look at my code for getTargetStates and 
>>>> getTargetState below [1].
>>>>
>>>> It is only with the following two lines present in getTargetState:
>>>>                      if( defaultHistoryContent != null &&
>>>> h.parent.exists("id") )
>>>> defaultHistoryContent.set(h.parent.get("id"),
>>>> h.transition().next());
>>>> ..that 579 passes.
>>>>
>>>> As mentioned, I did not look at it in depth and will not be able to 
>>>> spend more
>>>> time on it over the next few days unfortunately.
>>>>
>>>> So in summary, after adding the published additions to the 
>>>> algorithm, test579
>>>> did not pass.
>>>> It was only after the changes to getTargetStates that it did.
>>>> Hope this helps for now.
>>>>
>>>> Thanks,
>>>> Zjnue
>>>>
>>>> [1]
>>>>
>>>>      function getTargetStates( node : Node, ?defaultHistoryContent :
>>>> Hash<Iterable<Node>> ) : List<Node> {
>>>>          var l = new List<Node>();
>>>>          if( !node.exists("target") )
>>>>              return l;
>>>>          var ids = node.get("target").split(" ");
>>>>          var top = node;
>>>>          while( top.parent != null && !top.isTScxml() )
>>>>              top = top.parent;
>>>>          for( id in ids ) {
>>>>              var ts = getTargetState(top, id, defaultHistoryContent);
>>>>              for( tss in ts )
>>>>                  l.add( tss );
>>>>          }
>>>>          return l;
>>>>      }
>>>>
>>>>      function getTargetState( s : Node, id : String, 
>>>> ?defaultHistoryContent :
>>>> Hash<Iterable<Node>> ) : List<Node> {
>>>>          if( s.get("id") == id )
>>>>              return [s].toList();
>>>>          else {
>>>>              for( child in s.getChildStates() ) {
>>>>                  var ss = getTargetState(child, id, 
>>>> defaultHistoryContent);
>>>>                  if( ss != null )
>>>>                      return ss;
>>>>              }
>>>>              for( h in s.history() ) {
>>>>                  var hh = getTargetState(h, id);
>>>>                  if( hh != null ) {
>>>>                      if( defaultHistoryContent != null &&
>>>> h.parent.exists("id") )
>>>> defaultHistoryContent.set(h.parent.get("id"),
>>>> h.transition().next());
>>>>                      return historyValue.exists( h.get("id") ) ?
>>>>                          historyValue.get( h.get("id") ) :
>>>>                          getTargetStates( h.transition().next(),
>>>> defaultHistoryContent );
>>>>                  }
>>>>              }
>>>>          }
>>>>          return null;
>>>>      }
>>>>
>>>>
>>>>
>>>>     On 3/28/2014 8:51 PM, Zjnue Brzavi wrote:
>>>>>
>>>>>         I've added test579 to the suite.  Let me know if there are 
>>>>> problems
>>>>>         with it or if you think there need to be more/different 
>>>>> tests.--
>>>>>
>>>>>
>>>>>     Hi,
>>>>>
>>>>>     Not had a very good look yet, but it appears we'll need to pass
>>>>>     defaultHistoryContent to getTargetStates as well, as it is 
>>>>> another area
>>>>>     where the algorithm is skipping past some history elements 
>>>>> without
>>>>>     considering their executable content. This diff passes test579 :
>>>>> https://github.com/zjnue/hscxml/commit/4b9091470d3c7c1995e6b41900535e0437ec3eb4 
>>>>>
>>>>>     Another test or 2 on the subject is probably a good idea.
>>>>>
>>>>>     Best regards,
>>>>>     Zjnue
>>>>
>>>>     --
>>>>     Jim Barnett
>>>>     Genesys
>>>>
>>>>
>>>
>>>
>>
>
>

-- 
Jim Barnett
Genesys

Received on Wednesday, 2 April 2014 14:10:51 UTC