You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2004/11/21 23:28:34 UTC
svn commit: r106131 - in cocoon/branches/BRANCH_2_1_X/src/blocks/forms: java/org/apache/cocoon/forms/formmodel test/org/apache/cocoon/forms/formmodel
Author: sylvain
Date: Sun Nov 21 14:28:33 2004
New Revision: 106131
Added:
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.java (contents, props changed)
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.model.xml (contents, props changed)
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.xtest
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/WidgetTestHelper.java (contents, props changed)
Modified:
cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java
Log:
Fix a bug when Field.setValue() is called, add some tests
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java
Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java?view=diff&rev=106131&p1=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java&r1=106130&p2=cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java&r2=106131
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/java/org/apache/cocoon/forms/formmodel/Field.java Sun Nov 21 14:28:33 2004
@@ -155,11 +155,27 @@
"\" (expected " + getDatatype().getTypeClass() +
", got " + newValue.getClass() + ").");
}
- Object oldValue = this.value;
- boolean changed = ! (oldValue == null ? "" : oldValue).equals(newValue == null ? "" : newValue);
+
+ // Is it a new value?
+ boolean changed;
+ if (this.valueState == VALUE_UNPARSED) {
+ // Current value was not parsed
+ changed = true;
+ } else if (this.value == null) {
+ // Is current value not null?
+ changed = (newValue != null);
+ } else {
+ // Is current value different?
+ changed = !this.value.equals(newValue);
+ }
+
// Do something only if value is different or null
// (null allows to reset validation error)
if (changed || newValue == null) {
+ // Do we need to call listeners? If yes, keep (and parse if needed) old value.
+ boolean callListeners = changed && hasValueChangedListeners();
+ Object oldValue = callListeners ? getValue() : null;
+
this.value = newValue;
this.validationError = null;
// Force validation, even if set by the application
@@ -169,7 +185,8 @@
} else {
this.enteredValue = null;
}
- if (changed && hasValueChangedListeners()) {
+
+ if (callListeners) {
getForm().addWidgetEvent(new ValueChangedEvent(this, oldValue, newValue));
}
}
@@ -200,7 +217,13 @@
// Only convert if the text value actually changed. Otherwise, keep the old value
// and/or the old validation error (allows to keep errors when clicking on actions)
- if (!(newEnteredValue == null ? "" : newEnteredValue).equals((enteredValue == null ? "" : enteredValue))) {
+ boolean changed;
+ if (enteredValue == null) {
+ changed = (newEnteredValue != null);
+ } else {
+ changed = !enteredValue.equals(newEnteredValue);
+ }
+ if (changed) {
// If we have some value-changed listeners, we must make sure the current value has been
// parsed, to fill the event. Otherwise, we don't need to spend that extra CPU time.
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.java
Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.java?view=auto&rev=106131
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.java Sun Nov 21 14:28:33 2004
@@ -0,0 +1,227 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cocoon.forms.formmodel;
+
+import org.apache.cocoon.core.container.ContainerTestCase;
+import org.apache.cocoon.environment.mock.MockRequest;
+import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.event.ValueChangedEvent;
+import org.apache.cocoon.forms.event.ValueChangedListener;
+import org.w3c.dom.Document;
+
+/**
+ * Test case for CForm's Field widget
+ *
+ * @version $Id$
+ */
+
+public class FieldTestCase extends ContainerTestCase {
+
+ public static final String VALUE_PATH = "fi:fragment/fi:field/fi:value";
+ public static final String VALIDATION_PATH = "fi:fragment/fi:field/fi:validation-message";
+
+
+ /**
+ * Nominal test where the request data is syntactically correct and validates
+ */
+ public void testValueDoesParseAndValidate() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("intfield");
+ Action button = (Action)form.getChild("action");
+ MockRequest request;
+
+ request = new MockRequest();
+ request.addParameter("intfield", "11");
+ request.addParameter("action", "pressed");
+ form.process(new FormContext(request));
+
+ // No parsing nor validation where performed
+ Document doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed value", "11", VALUE_PATH, doc);
+ WidgetTestHelper.assertXPathNotExists("Validation error", VALIDATION_PATH, doc);
+
+ // Now do some parsing.
+ assertEquals("Field value", new Integer(11), field.getValue());
+ // And still no validation error (do not call getValidationError() as it does validate)
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathNotExists("Validation error", VALIDATION_PATH, doc);
+
+ // Now validate
+ assertTrue("Field does validate", field.validate());
+ assertNull("getValidationError() null after validation", field.getValidationError());
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathNotExists("Validation error", VALIDATION_PATH, doc);
+ }
+
+ /**
+ * Request data is not syntactically correct
+ */
+ public void testValueDoesNotParse() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("intfield");
+ Action button = (Action)form.getChild("action");
+ MockRequest request;
+
+ request = new MockRequest();
+ request.addParameter("intfield", "foo");
+ request.addParameter("action", "pressed");
+ form.process(new FormContext(request));
+
+ // No parsing nor validation where performed
+ Document doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed velue", "foo", VALUE_PATH, doc);
+ WidgetTestHelper.assertXPathNotExists("Validation error before parse", VALIDATION_PATH, doc);
+
+ // Now do some parsing. Will return null as it's not parseable
+ assertNull("Field value", field.getValue());
+ // But still no validation error
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed value", "foo", VALUE_PATH, doc);
+ WidgetTestHelper.assertXPathNotExists("Validation error after parse", VALIDATION_PATH, doc);
+
+ // Now validate
+ assertFalse("Field validation", field.validate());
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed velue", "foo", VALUE_PATH, doc);
+ WidgetTestHelper.assertXPathExists("Validation not null after parse", VALIDATION_PATH, doc);
+ assertNotNull("getValidationError() not null after validation", field.getValidationError());
+ }
+
+ /**
+ * Request data is syntactically correct but doesn't validate
+ */
+ public void testValueDoesNotValidate() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("intfield");
+ Action button = (Action)form.getChild("action");
+ MockRequest request;
+
+ request = new MockRequest();
+ request.addParameter("intfield", "1");
+ request.addParameter("action", "pressed");
+ form.process(new FormContext(request));
+
+ // No parsing nor validation where performed
+ Document doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed value", "1", VALUE_PATH, doc);
+ WidgetTestHelper.assertXPathNotExists("Validation error before parse", VALIDATION_PATH, doc);
+
+ // Now do some parsing. Will return null although syntactically correct as it's invalid
+ assertNull("Field value", field.getValue());
+ // But still no validation error
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathNotExists("Validation error after parse", VALIDATION_PATH, doc);
+
+ // Now validate
+ assertFalse("Field validation", field.validate());
+ doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathExists("Validation error after validation", VALIDATION_PATH, doc);
+ assertNotNull("getValidationError() not null after validation", field.getValidationError());
+ }
+
+ /**
+ * Test that a field's value is properly set by a call to setValue("") with an
+ * empty string when the field is in unparsed state (there used to be a bug in
+ * that case)
+ */
+ public void testSetEmptyValueWhenValueChangedOnRequest() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("stringfield");
+ Action button = (Action)form.getChild("action");
+ MockRequest request;
+
+ // Set a value in stringfield and submit with an action
+ // (no validation, thus no call to doParse())
+ request = new MockRequest();
+ request.addParameter("stringfield", "bar");
+ request.addParameter("action", "pressed");
+ form.process(new FormContext(request));
+
+ // Verify submit widget, just to be sure that validation did not occur
+ assertEquals("Form submit widget", button, form.getSubmitWidget());
+
+ // Set the value to an empty string. In that case, a faulty test made
+ // it actually ignore it when state was VALUE_UNPARSED
+ field.setValue("");
+
+ // Check value by various means
+ Document doc = WidgetTestHelper.getWidgetFragment(field, null);
+ WidgetTestHelper.assertXPathEquals("Displayed value", "", VALUE_PATH, doc);
+ assertEquals("Datatype string conversion", "", field.getDatatype().convertToString(field.value, null));
+ assertEquals("Field value", "", (String)field.getValue());
+ }
+
+ /**
+ * Test that the previous field value is correctly passed to event listeners
+ * even if it was not already parsed.
+ */
+ public void testOldValuePresentInEventEvenIfNotParsed() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("stringfield");
+ Action button = (Action)form.getChild("action");
+ MockRequest request;
+
+ // Set a value on "stringfield", and submit using an action so that
+ // it stays in unparsed state
+ request = new MockRequest();
+ request.addParameter("stringfield", "foo");
+ request.addParameter("action", "pressed");
+ form.process(new FormContext(request));
+
+ // Now add an event listener that will check old an new value
+ field.addValueChangedListener(new ValueChangedListener (){
+ public void valueChanged(ValueChangedEvent event) {
+ assertEquals("Old value", "foo", (String)event.getOldValue());
+ assertEquals("New value", "bar", (String)event.getNewValue());
+ }
+ });
+
+ // Change value to "bar", still without explicit validation
+ // That will call the event listener
+ request = new MockRequest();
+ request.addParameter("stringfield", "bar");
+ request.addParameter("button", "pressed");
+ form.process(new FormContext(request));
+ }
+
+ /**
+ * Request parameters are not read when a field is not in active state
+ */
+ public void testParameterNotReadWhenDisabled() throws Exception {
+ Form form = WidgetTestHelper.loadForm(getManager(), this, "FieldTestCase.model.xml");
+ Field field = (Field)form.getChild("stringfield");
+ MockRequest request;
+
+ // Disable the form
+ form.setState(WidgetState.DISABLED);
+ field.setValue("foo");
+
+ request = new MockRequest();
+ request.addParameter("stringfield", "bar");
+ form.process(new FormContext(request));
+
+ // Check that "bar" was not read
+ assertEquals("foo", field.getValue());
+
+ // Switch back to active and resumbit the same request
+ form.setState(WidgetState.ACTIVE);
+ form.process(new FormContext(request));
+
+ // Should have changed now
+ assertEquals("bar", field.getValue());
+ }
+}
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.model.xml
Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.model.xml?view=auto&rev=106131
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.model.xml Sun Nov 21 14:28:33 2004
@@ -0,0 +1,19 @@
+<fd:form xmlns:fd="http://apache.org/cocoon/forms/1.0#definition">
+ <fd:widgets>
+ <fd:field id="stringfield">
+ <fd:datatype base="string"/>
+ </fd:field>
+
+ <fd:field id="intfield">
+ <fd:datatype base="integer">
+ <fd:convertor type="plain"/>
+ </fd:datatype>
+ <fd:validation>
+ <fd:range min="10"/>
+ </fd:validation>
+ </fd:field>
+
+ <fd:action id="action" action-command="blah"/>
+
+ </fd:widgets>
+</fd:form>
\ No newline at end of file
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.xtest
Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.xtest?view=auto&rev=106131
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/FieldTestCase.xtest Sun Nov 21 14:28:33 2004
@@ -0,0 +1,81 @@
+<?xml version="1.0" ?>
+<!--
+ Copyright 1999-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<testcase>
+ <roles>
+
+ <role name="org.apache.cocoon.forms.datatype.DatatypeManager"
+ shorthand="forms-datatype"
+ default-class="org.apache.cocoon.forms.datatype.DefaultDatatypeManager"/>
+
+ <role name="org.apache.cocoon.forms.expression.ExpressionManager"
+ shorthand="forms-expression"
+ default-class="org.apache.cocoon.forms.expression.DefaultExpressionManager"/>
+
+ <role name="org.apache.cocoon.forms.FormManager"
+ shorthand="forms-formmanager"
+ default-class="org.apache.cocoon.forms.DefaultFormManager"/>
+
+ <role name="org.apache.cocoon.forms.CacheManager"
+ shorthand="forms-cachemanager"
+ default-class="org.apache.cocoon.forms.DefaultCacheManager"/>
+
+ <role name="org.apache.cocoon.forms.validation.WidgetValidatorBuilderSelector"
+ shorthand="forms-validators"
+ default-class="org.apache.cocoon.components.ExtendedComponentSelector"/>
+
+ <role name="org.apache.cocoon.forms.event.WidgetListenerBuilderSelector"
+ shorthand="forms-widgetlisteners"
+ default-class="org.apache.cocoon.components.ExtendedComponentSelector"/>
+</roles>
+
+ <components>
+ <forms-datatype logger="forms">
+ <datatypes>
+ <datatype name="string" src="org.apache.cocoon.forms.datatype.typeimpl.StringTypeBuilder">
+ <convertors default="dummy" plain="dummy">
+ <convertor name="dummy" src="org.apache.cocoon.forms.datatype.convertor.DummyStringConvertorBuilder"/>
+ </convertors>
+ </datatype>
+ <datatype name="integer" src="org.apache.cocoon.forms.datatype.typeimpl.IntegerTypeBuilder">
+ <convertors default="formatting" plain="plain">
+ <convertor name="plain" src="org.apache.cocoon.forms.datatype.convertor.PlainIntegerConvertorBuilder"/>
+ <convertor name="formatting" src="org.apache.cocoon.forms.datatype.convertor.FormattingIntegerConvertorBuilder"/>
+ </convertors>
+ </datatype>
+ </datatypes>
+ <!--validation-rules>
+ <validation-rule name="range" src="org.apache.cocoon.forms.datatype.validationruleimpl.RangeValidationRuleBuilder"/>
+ </validation-rules-->
+ </forms-datatype>
+
+ <forms-validators>
+ <validator name="range" class="org.apache.cocoon.forms.validation.impl.RangeValidatorBuilder"/>
+ </forms-validators>
+
+ <forms-formmanager>
+ <widgets>
+ <widget name="form" src="org.apache.cocoon.forms.formmodel.FormDefinitionBuilder"/>
+ <widget name="field" src="org.apache.cocoon.forms.formmodel.FieldDefinitionBuilder"/>
+ <widget name="action" src="org.apache.cocoon.forms.formmodel.ActionDefinitionBuilder"/>
+ </widgets>
+ </forms-formmanager>
+
+ <forms-expression logger="forms.expression"/>
+
+ </components>
+
+</testcase>
Added: cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/WidgetTestHelper.java
Url: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/WidgetTestHelper.java?view=auto&rev=106131
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/forms/test/org/apache/cocoon/forms/formmodel/WidgetTestHelper.java Sun Nov 21 14:28:33 2004
@@ -0,0 +1,140 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cocoon.forms.formmodel;
+
+import java.util.Locale;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.Assert;
+
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.forms.Constants;
+import org.apache.cocoon.forms.FormManager;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.Pointer;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.NamespaceSupport;
+
+/**
+ * Helper class to build Widget test cases.
+ *
+ * @version $Id$
+ */
+public class WidgetTestHelper {
+
+ // Private constructor as we only have static methods
+ private WidgetTestHelper() {}
+
+ /**
+ * Get the result of a widget's generateSaxFragment() method as a Document.
+ * <p>
+ * The widget's fragment is encapsulated in a root <fi:fragment> element,
+ * since there's no guarantee that a widget outputs a single top-level element
+ * (there can be several elements, or even none if the widget is invisible)
+ *
+ * @param widget the widget of which we want the fragment
+ * @param locale the locale to be used to generate the fragment
+ * @return the document containing the fragment
+ */
+ public static Document getWidgetFragment(Widget widget, Locale locale) throws SAXException {
+
+ DOMBuilder domBuilder = new DOMBuilder();
+ // Start document and "fi:fragment" root element
+ domBuilder.startDocument();
+ domBuilder.startPrefixMapping(Constants.INSTANCE_PREFIX, Constants.INSTANCE_NS);
+ // FIXME: why simply declaring the prefix isn't enough?
+ AttributesImpl attr = new AttributesImpl();
+ attr.addCDATAAttribute(NamespaceSupport.XMLNS, "fi:", "xmlns:fi", Constants.INSTANCE_NS);
+ domBuilder.startElement(Constants.INSTANCE_NS, "fragment", Constants.INSTANCE_PREFIX_COLON + "fragment", attr);
+
+ widget.generateSaxFragment(domBuilder, locale);
+
+ // End "fi:fragment" element and document
+ domBuilder.endElement(Constants.INSTANCE_NS, "fragment", Constants.INSTANCE_PREFIX_COLON + "fragment");
+ domBuilder.endPrefixMapping(Constants.INSTANCE_PREFIX);
+ domBuilder.endDocument();
+
+ // Return the document
+ return domBuilder.getDocument();
+ }
+
+ public static void assertXPathEquals(String expected, String xpath, Document doc) {
+ // use xpath as the message
+ assertXPathEquals(xpath, expected, xpath, doc);
+ }
+
+ public static void assertXPathEquals(String message, String expected, String xpath, Document doc) {
+ JXPathContext ctx = JXPathContext.newContext(doc);
+ ctx.setLenient(true);
+ Assert.assertEquals(message, expected, ctx.getValue(xpath));
+ }
+
+ public static void assertXPathExists(String xpath, Document doc) {
+ // use xpath as message
+ assertXPathExists(xpath, xpath, doc);
+ }
+
+ public static void assertXPathExists(String message, String xpath, Document doc) {
+ JXPathContext ctx = JXPathContext.newContext(doc);
+ ctx.setLenient(true);
+ Pointer pointer = ctx.getPointer(xpath);
+ Assert.assertNotNull(message, pointer.getNode());
+ }
+
+ public static void assertXPathNotExists(String xpath, Document doc) {
+ // use xpath as message
+ assertXPathNotExists(xpath, xpath, doc);
+ }
+
+ public static void assertXPathNotExists(String message, String xpath, Document doc) {
+ JXPathContext ctx = JXPathContext.newContext(doc);
+ ctx.setLenient(true);
+ Pointer pointer = ctx.getPointer(xpath);
+ Assert.assertNull(message, pointer.getNode());
+ }
+
+ /**
+ * Load a Form whose definition relative to a given object (typically, the TestCase class).
+ *
+ * @param manager the ServiceManager that will be used to create the form
+ * @param obj the object relative to which the resource will be read
+ * @param resource the relative resource name for the form definition
+ * @return the Form
+ * @throws Exception
+ */
+ public static Form loadForm(ServiceManager manager, Object obj, String resource) throws Exception {
+ // Load the document
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ // Grmbl... why isn't this true by default?
+ factory.setNamespaceAware(true);
+ DocumentBuilder parser = factory.newDocumentBuilder();
+ Document doc = parser.parse(obj.getClass().getResource(resource).toExternalForm());
+
+ // Create the form
+ FormManager formManager = (FormManager)manager.lookup(FormManager.ROLE);
+ try {
+ return formManager.createForm(doc.getDocumentElement());
+ } finally {
+ manager.release(formManager);
+ }
+ }
+}