"Best practice" wanted: How to implement asynchronous serverside constraint checking on an instance

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

"Best practice" wanted: How to implement asynchronous serverside constraint checking on an instance

Henrik Pettersen
David,

thank you, that seemed to do the trick. Much obliged :-) But I ran into a different problem, which I think can be summed up like this:

1. How do you implement serverside constraint checking on an instance, BEFORE submitting it ( i.e. asynchronously)?
2. In the case of failing this test: If your serverside constraint checking provides additional information about what the problem is, how do you get these hints displayed on the page?
(3. In particular, how do you do this with an instance that contains a variable length list of a (constraint-checked) node?)

I went through a few iterations trying to solve this, so I thought I would share my notes with the Orbeon community (at the risk of looking a little foolish). See earlier messages in this thread, attached example and walkthrough at the end of this email for more background information.

My first approach was to use 2 instances: one for the final submission of the data (final submission instance), and one for the server side constraint checking (checking instance). Keep in mind that the length of my list of aspic:premise's can be changed in the user interface (xforms:insert/xforms:delete).

The trouble with this approach, is that you have to do some very carefull balancing of the index of the aspic:premise in the 2 instances (The xforms:repeat uses the final submission instance, where as the "traffic lights" uses the contents of the checking instance.). I could never get this to work for me :-(

I abandoned this approach in favor of merging the checking instance and the final submission instance into just one instance, submitting this both for the checking and the final submission. I then used xforms:bind/@constraint to make sure that the aspic:rule/aspic:premise was aspic:rule/aspic:premise/aspic:test/aspic:parseable (more details below).

Can you spot the problem? Exactly. Sharing the same instance for both constraints checking and final submission and using xforms:bind/@constraint, causes this issue:

1. Page is initialized. All expressions are parseable.
2. The user enters a non-parseable premise
3. The asynchronous constraints checker cheerfully submits the instance to be checked
4. The instance comes back with /aspic:rule/aspic:premise/aspic:test/aspic:parseable == 'false'
5. The xforms:bind/@constraint is now evaluating to 'false', and is therefore not allowing final submission (... and here's the rub) nor any more submissions to the constraints checker!
6. The user is stuck with an instance that violates the xforms:bind/@constraint, unable to do the final submission.

I'll give you some more detail on this last issue (this is as far as I have come):

1. A user is presented with a page that has a form on it, with a variable length list of "premise" elements in the instance. Each premise instance is rendered as an inputbox on the page. Here is the instance:

    <xforms:instance id="rule-instance">
      <aspic:rule xmlns:aspic=" http://www.cruk.com/aspic/editor/v1">
          <aspic:premise>
              <aspic:expression>penguin(X)</aspic:expression>
              <aspic:test>
                  <aspic:parseable>true</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>

          <aspic:premise>
              <aspic:expression>flies(X)</aspic:expression>
              <aspic:test>
                  <aspic:parseable>true</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>
      </aspic:rule>
    </xforms:instance>

2. The validation of the user entered data is a combination of using xforms:bind and some server-side parsing and checking that can not be easily expressed as a regular expression in xforms:bind. Here are the xforms:bind restrictions:

    <xforms:bind nodeset="aspic:premise/aspic:expression" type="xs:string" required="true()"/>
    <xforms:bind nodeset="aspic:premise" constraint="aspic:test/aspic:parseable = 'true'"/>

   Here is the submission for doing the constraint checking on the premise element:

    <xforms:submission id="test-rule-submission"
                       ref="instance('rule-instance')"
                       method="post"
                       action="/knowledgebase/testrule"
                       replace="instance"/>
    
   Here is the submission for persisting the user entered data and navigating away from the page:

    <xforms:submission id="update-rule-submission"
                       ref="instance('rule-instance')"
                       method="post"
                       action="/rule/update"/>

3. Note that I am using the same instance ('rule-instance') for both submissions. I have an xforms:repeat on the page, which loops over each premise. If /aspic:rule/aspic:premise/aspic:test/aspic:parseable is 'true', I display a "green trafficlight". If the value is 'false', I display a "red trafficlight":

    <xforms:repeat nodeset="aspic:premise" id="premise-repeat">

        <!-- display the input box for the premise element -->
        <xforms:input ref="aspic:expression" selection="open" incremental="true" class="input">
            <xforms:label class="fixed-width">Premise</xforms:label>
            <xforms:alert>Premise is not parseable</xforms:alert>
            <xforms:action ev:event="xforms-value-changed">
                <xforms:send submission="test-rule-submission"/>
            </xforms:action>
        </xforms:input>

        <!-- red light -->
        <xforms:group ref="xxforms:repeat-current('premise-repeat')/aspic:test/aspic:parseable[ . = 'false']"> Red</xforms:group>

        <!-- green light -->
        <xforms:group ref="xxforms:repeat-current('premise-repeat')/aspic:test/aspic:parseable[ . = 'true']"> Green</xforms:group>

        <xhtml:br/>
    </xforms:repeat>

4. As soon as the users enters a premise that evaluates aspic:premise/aspic:test/aspic:parseable to false, the page becomes 'locked', i.e. no more submissions can be done.

I have attached a standalone example of this last issue, but I am not sure where to go from here.

No solution, but hopefully someone will find this information helpfull :-)

Sincerely,
Henrik Pettersen
Advanced Computation Laboratory
Cancer Research UK

On 11/22/06, David McIntyre <[hidden email]> wrote:

    Perhaps the constraint attribute would be more suitable than the required attribute?  Would the following work?
     
    <xforms:bind nodeset="instance('rule-instance')" constraint="count(aspic:premise) gt 0"> <!-- Test 1 -->
       <xforms:bind nodeset="aspic:premise/aspic:test/aspic:parseable" constraint=". = 'true'"/> <!-- Test 2 -->
    </xforms:bind>
    Cheers,
     
        Dave McIntyre
     
     
    Dave McIntyre
    Software Developer     
    2nd Floor, Orion House, cnr Enfield & Mary St, Mt Eden, PO Box 8273, Auckland, New Zealand
    M.+64 21 212 8087 P.+64 9 638 0600 F.+64 9 638 0699
    S.dave.mcintyre [hidden email] W.www.orionhealth.com
        



    This e-mail and any attachments are intended only for the person to whom it is addressed and may contain privileged, proprietary, or other data protected from disclosure under applicable law. If you are not the addressee or the person responsible for delivering this to the addressee you are hereby notified that reading, copying or distributing this transmission is prohibited. If you have received this e-mail in error, please telephone us immediately and remove all copies of it from your system. Thank you for your co-operation.


    >>> "Henrik Pettersen" <[hidden email]> 22/11/2006 11:45 a.m. >>>

    All,

    I have a couple of questions on Xforms bind that I hoped one of you might be able to assist me with.

    I have this instance:

      <aspic:rule xmlns:aspic=" http://www.cruk.com/aspic/editor/v1">
          <aspic:premise>
              <aspic:expression>penguin(X)</aspic:expression>
              <aspic:test>
                  <aspic:parseable>true</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>

          <aspic:premise>
              <aspic:expression>penguin(X)</aspic:expression>
              <aspic:test>
                  <aspic:parseable>true</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>
      </aspic:rule>


      There are 2 tests I want the instance to pass before it gets submitted.
      1. There must be at least one premise element. The premise elements can be added and removed,
          and the requirement is that there exists at least one premise at the time of submission
      2. The value at /aspic:rule/aspic:premise/aspic:test/aspic:parseable must be 'true'

      In the example above, the instance is valid. Here is an instance that violate the first rule:

      <aspic:rule xmlns:aspic=" http://www.cruk.com/aspic/editor/v1 ">
      </aspic:rule>

      And here is an instance that violate the second rule:

        <aspic:rule xmlns:aspic=" http://www.cruk.com/aspic/editor/v1 ">
          <aspic:premise>
              <aspic:expression>penguin(X)</aspic:expression>
              <aspic:test>
                  <aspic:parseable>true</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>

          <aspic:premise>
              <aspic:expression>penguin(X</aspic:expression>
              <aspic:test>
                  <aspic:parseable>false</aspic:parseable>
                  <aspic:hint>Expression complete</aspic:hint>
              </aspic:test>
          </aspic:premise>
      </aspic:rule>

    Question is, how do I enforce these restrictions using XForms bind?

    Here is my current attempt, which is not doing what I want:

      <xforms:bind nodeset="instance('rule-instance')">
       <xforms:bind nodeset="aspic:premise" required="last() > 1"/> <!-- Test 1 -->
       <xforms:bind nodeset="aspic:premise/aspic:test/aspic:parseable" required=". = true()"/> <!-- Test 2 -->
      </xforms:bind>


    Any ideas, anyone?

    Sincerely,
    Henrik Pettersen
    Advanced Computation Laboratory
    Cancer Research UK


    --
    You receive this message as a subscriber of the [hidden email] mailing list.
    To unsubscribe: mailto:[hidden email]
    For general help: mailto: [hidden email]?subject=help
    ObjectWeb mailing lists service home page: http://www.objectweb.org/wws





--
You receive this message as a subscriber of the [hidden email] mailing list.
To unsubscribe: mailto:[hidden email]
For general help: mailto:[hidden email]?subject=help
ObjectWeb mailing lists service home page: http://www.objectweb.org/wws

server.side.constraint.checking.testcase.zip (6K) Download Attachment