fix and unit test for Schema2XForms

- adding a unit test.  currently just tests repeat properties and instance data.
- fix for problem with obtaining particle for element references.  addresses bug WCM-508
- new regenerate renditions icons from linton


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6010 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Ariel Backenroth
2007-06-18 19:06:51 +00:00
parent 834f2ab814
commit e2dd65b1b4
9 changed files with 480 additions and 102 deletions

View File

@@ -272,7 +272,8 @@ public class Schema2XForms
formSection, formSection,
schema, schema,
rootElementDecl, rootElementDecl,
"/" + getElementName(rootElementDecl, xformsDocument), "/" + this.getElementName(rootElementDecl, xformsDocument),
new SchemaUtil.Occurance(1, 1),
resourceBundle); resourceBundle);
if (rootGroup.getNodeName() != NamespaceConstants.XFORMS_PREFIX + ":group") if (rootGroup.getNodeName() != NamespaceConstants.XFORMS_PREFIX + ":group")
{ {
@@ -818,27 +819,6 @@ public class Schema2XForms
return result; return result;
} }
private Element addAnyType(final Document xformsDocument,
final Element modelSection,
final Element formSection,
final XSModel schema,
final XSTypeDefinition controlType,
final XSElementDeclaration owner,
final String pathToRoot,
final ResourceBundle resourceBundle)
{
return this.addSimpleType(xformsDocument,
modelSection,
formSection,
schema,
controlType,
owner.getName(),
owner,
pathToRoot,
SchemaUtil.getOccurance(owner),
resourceBundle);
}
private void addAttributeSet(final Document xformsDocument, private void addAttributeSet(final Document xformsDocument,
final Element modelSection, final Element modelSection,
final Element defaultInstanceElement, final Element defaultInstanceElement,
@@ -973,6 +953,7 @@ public class Schema2XForms
final XSComplexTypeDefinition controlType, final XSComplexTypeDefinition controlType,
final XSElementDeclaration owner, final XSElementDeclaration owner,
String pathToRoot, String pathToRoot,
final SchemaUtil.Occurance occurs,
boolean relative, boolean relative,
final boolean checkIfExtension, final boolean checkIfExtension,
final ResourceBundle resourceBundle) final ResourceBundle resourceBundle)
@@ -1000,13 +981,13 @@ public class Schema2XForms
formSection, formSection,
owner, owner,
resourceBundle); resourceBundle);
final SchemaUtil.Occurance o = SchemaUtil.getOccurance(owner); // final SchemaUtil.Occurance o = SchemaUtil.getOccurance(owner);
final Element repeatSection = this.addRepeatIfNecessary(xformsDocument, final Element repeatSection = this.addRepeatIfNecessary(xformsDocument,
modelSection, modelSection,
groupElement, groupElement,
controlType, controlType,
o, pathToRoot,
pathToRoot); occurs);
if (repeatSection != groupElement) if (repeatSection != groupElement)
{ {
groupElement.setAttributeNS(NamespaceConstants.XFORMS_NS, groupElement.setAttributeNS(NamespaceConstants.XFORMS_NS,
@@ -1042,9 +1023,11 @@ public class Schema2XForms
modelSection, modelSection,
repeatSection, repeatSection,
schema, schema,
(XSSimpleTypeDefinition) base, (XSSimpleTypeDefinition)base,
owner.getName(),
owner, owner,
pathToRoot, pathToRoot,
occurs,
resourceBundle); resourceBundle);
} }
else else
@@ -1132,6 +1115,7 @@ public class Schema2XForms
final XSModel schema, final XSModel schema,
final XSElementDeclaration elementDecl, final XSElementDeclaration elementDecl,
final String pathToRoot, final String pathToRoot,
final SchemaUtil.Occurance occurs,
final ResourceBundle resourceBundle) final ResourceBundle resourceBundle)
throws FormBuilderException throws FormBuilderException
{ {
@@ -1158,22 +1142,26 @@ public class Schema2XForms
formSection, formSection,
schema, schema,
(XSSimpleTypeDefinition) controlType, (XSSimpleTypeDefinition) controlType,
elementDecl.getName(),
elementDecl, elementDecl,
pathToRoot, pathToRoot,
occurs,
resourceBundle); resourceBundle);
} }
if (controlType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE && if (controlType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
"anyType".equals(controlType.getName())) "anyType".equals(controlType.getName()))
{ {
return this.addAnyType(xformsDocument, return this.addSimpleType(xformsDocument,
modelSection, modelSection,
formSection, formSection,
schema, schema,
(XSComplexTypeDefinition)controlType, (XSComplexTypeDefinition)controlType,
elementDecl, elementDecl.getName(),
pathToRoot, elementDecl,
resourceBundle); pathToRoot,
occurs,
resourceBundle);
} }
if (controlType.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE) if (controlType.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE)
@@ -1237,22 +1225,21 @@ public class Schema2XForms
if (!relative) if (!relative)
{ {
LOGGER.debug("addElement: bind is not relative for " LOGGER.debug("addElement: bind is not relative for " + elementDecl.getName());
+ elementDecl.getName());
} }
else else
{ {
final SchemaUtil.Occurance o = SchemaUtil.getOccurance(elementDecl); // final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(elementDecl);
//create the bind in case it is a repeat //create the bind in case it is a repeat
LOGGER.debug("Adding empty bind for control " + controlType + LOGGER.debug("Adding empty bind for control " + controlType +
" type " + typeName + " type " + typeName +
" nodeset " + pathToRoot + " nodeset " + pathToRoot +
" occurs " + o); " occurs " + occurs);
// create the <xforms:bind> element and add it to the model. // create the <xforms:bind> element and add it to the model.
final Element bindElement = final Element bindElement =
this.createBind(xformsDocument, this.createBind(xformsDocument,
pathToRoot + (o.isRepeated() ? "[position() != last()]" : "")); pathToRoot + (occurs.isRepeated() ? "[position() != last()]" : ""));
final String bindId = bindElement.getAttributeNS(null, "id"); final String bindId = bindElement.getAttributeNS(null, "id");
modelSection.appendChild(bindElement); modelSection.appendChild(bindElement);
@@ -1260,7 +1247,7 @@ public class Schema2XForms
schema, schema,
controlType, controlType,
null, null,
o); occurs);
} }
return this.addComplexType(xformsDocument, return this.addComplexType(xformsDocument,
modelSection, modelSection,
@@ -1270,6 +1257,7 @@ public class Schema2XForms
(XSComplexTypeDefinition)controlType, (XSComplexTypeDefinition)controlType,
elementDecl, elementDecl,
pathToRoot, pathToRoot,
occurs,
true, true,
false, false,
resourceBundle); resourceBundle);
@@ -1343,6 +1331,7 @@ public class Schema2XForms
(XSComplexTypeDefinition)controlType, (XSComplexTypeDefinition)controlType,
elementDecl, elementDecl,
pathToRoot, pathToRoot,
SchemaUtil.getOccurance(elementDecl),
true, true,
false, false,
resourceBundle); resourceBundle);
@@ -1390,6 +1379,7 @@ public class Schema2XForms
(XSComplexTypeDefinition) type, (XSComplexTypeDefinition) type,
elementDecl, elementDecl,
pathToRoot, pathToRoot,
SchemaUtil.getOccurance(elementDecl),
true, true,
true, true,
resourceBundle); resourceBundle);
@@ -1464,7 +1454,7 @@ public class Schema2XForms
final XSComplexTypeDefinition controlType, final XSComplexTypeDefinition controlType,
final XSElementDeclaration owner, final XSElementDeclaration owner,
final String pathToRoot, final String pathToRoot,
final SchemaUtil.Occurance o, final SchemaUtil.Occurance occurs,
final boolean checkIfExtension, final boolean checkIfExtension,
final ResourceBundle resourceBundle) final ResourceBundle resourceBundle)
throws FormBuilderException throws FormBuilderException
@@ -1478,8 +1468,8 @@ public class Schema2XForms
modelSection, modelSection,
formSection, formSection,
owner.getTypeDefinition(), owner.getTypeDefinition(),
o, pathToRoot,
pathToRoot); occurs);
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
{ {
@@ -1492,16 +1482,15 @@ public class Schema2XForms
{ {
final XSParticle currentNode = (XSParticle)particles.item(counter); final XSParticle currentNode = (XSParticle)particles.item(counter);
XSTerm term = currentNode.getTerm(); XSTerm term = currentNode.getTerm();
final SchemaUtil.Occurance childOccurs = new SchemaUtil.Occurance(currentNode);
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
{ {
LOGGER.debug(" : next term = " + term.getName()); LOGGER.debug(" : next term = " + term.getName() +
" occurs = " + childOccurs);
} }
final SchemaUtil.Occurance childOccurs = new SchemaUtil.Occurance(currentNode);
if (term instanceof XSModelGroup) if (term instanceof XSModelGroup)
{ {
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
{ {
LOGGER.debug(" term is a group"); LOGGER.debug(" term is a group");
@@ -1590,6 +1579,7 @@ public class Schema2XForms
schema, schema,
element, element,
pathToRoot, pathToRoot,
childOccurs,
resourceBundle); resourceBundle);
} }
else else
@@ -1610,6 +1600,7 @@ public class Schema2XForms
schema, schema,
element, element,
pathToRoot, pathToRoot,
childOccurs,
resourceBundle); resourceBundle);
} }
} }
@@ -1634,9 +1625,11 @@ public class Schema2XForms
final XSModel schema, final XSModel schema,
final XSElementDeclaration element, final XSElementDeclaration element,
final String pathToRoot, final String pathToRoot,
final SchemaUtil.Occurance occurs,
final ResourceBundle resourceBundle) final ResourceBundle resourceBundle)
throws FormBuilderException throws FormBuilderException
{ {
LOGGER.debug("addElement to group " + element + " at " + pathToRoot);
//add it normally //add it normally
final String elementName = this.getElementName(element, xformsDocument); final String elementName = this.getElementName(element, xformsDocument);
final String path = (pathToRoot.length() == 0 final String path = (pathToRoot.length() == 0
@@ -1657,24 +1650,25 @@ public class Schema2XForms
schema, schema,
element, element,
path, path,
occurs,
resourceBundle); resourceBundle);
final SchemaUtil.Occurance elementOccurs = SchemaUtil.getOccurance(element); // final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(element);
LOGGER.debug("adding " + (elementOccurs.maximum == 1 LOGGER.debug("adding " + (occurs.maximum == 1
? 1 ? 1
: elementOccurs.minimum + 1) + : occurs.minimum + 1) +
" default instance element for " + elementName + " default instance element for " + elementName +
" at path " + path); " at path " + path);
// update the default instance // update the default instance
if (elementOccurs.isRepeated()) if (occurs.isRepeated())
{ {
LOGGER.debug("adding " + (elementOccurs.minimum + 1) + LOGGER.debug("adding " + (occurs.minimum + 1) +
" default instance elements for " + elementName + " default instance elements for " + elementName +
" at path " + path); " at path " + path);
for (int i = 0; i < elementOccurs.minimum + 1; i++) for (int i = 0; i < occurs.minimum + 1; i++)
{ {
final Element e = (Element)newDefaultInstanceElement.cloneNode(true); final Element e = (Element)newDefaultInstanceElement.cloneNode(true);
if (i == elementOccurs.minimum) if (i == occurs.minimum)
{ {
e.setAttributeNS(NamespaceService.ALFRESCO_URI, e.setAttributeNS(NamespaceService.ALFRESCO_URI,
NamespaceService.ALFRESCO_PREFIX + ":prototype", NamespaceService.ALFRESCO_PREFIX + ":prototype",
@@ -1687,7 +1681,7 @@ public class Schema2XForms
{ {
LOGGER.debug("adding one default instance element for " + elementName + LOGGER.debug("adding one default instance element for " + elementName +
" at path " + path); " at path " + path);
if (elementOccurs.minimum == 0) if (occurs.minimum == 0)
{ {
newDefaultInstanceElement.setAttributeNS(NamespaceConstants.XMLSCHEMA_INSTANCE_NS, newDefaultInstanceElement.setAttributeNS(NamespaceConstants.XMLSCHEMA_INSTANCE_NS,
NamespaceConstants.XMLSCHEMA_INSTANCE_PREFIX + ":nil", NamespaceConstants.XMLSCHEMA_INSTANCE_PREFIX + ":nil",
@@ -1704,8 +1698,8 @@ public class Schema2XForms
final Element modelSection, final Element modelSection,
final Element formSection, final Element formSection,
final XSTypeDefinition controlType, final XSTypeDefinition controlType,
final SchemaUtil.Occurance o , final String pathToRoot,
final String pathToRoot) final SchemaUtil.Occurance o)
{ {
// add xforms:repeat section if this element re-occurs // add xforms:repeat section if this element re-occurs
@@ -1789,13 +1783,14 @@ public class Schema2XForms
final String owningElementName, final String owningElementName,
final XSObject owner, final XSObject owner,
final String pathToRoot, final String pathToRoot,
final SchemaUtil.Occurance o, final SchemaUtil.Occurance occurs,
final ResourceBundle resourceBundle) final ResourceBundle resourceBundle)
{ {
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
{ {
LOGGER.debug("addSimpleType for " + controlType.getName() + LOGGER.debug("addSimpleType for " + controlType.getName() +
" (owningElementName=" + owningElementName + ")"); " (owningElementName=" + owningElementName + ")" +
" occurs = " + occurs);
if (owner != null) if (owner != null)
{ {
LOGGER.debug("owner is " + owner.getClass() + LOGGER.debug("owner is " + owner.getClass() +
@@ -1805,13 +1800,13 @@ public class Schema2XForms
// create the <xforms:bind> element and add it to the model. // create the <xforms:bind> element and add it to the model.
Element bindElement = Element bindElement =
this.createBind(xformsDocument, pathToRoot + (o.isRepeated() ? "[position() != last()]" : "")); this.createBind(xformsDocument, pathToRoot + (occurs.isRepeated() ? "[position() != last()]" : ""));
String bindId = bindElement.getAttributeNS(null, "id"); String bindId = bindElement.getAttributeNS(null, "id");
modelSection.appendChild(bindElement); modelSection.appendChild(bindElement);
bindElement = this.startBindElement(bindElement, schema, controlType, owner, o); bindElement = this.startBindElement(bindElement, schema, controlType, owner, occurs);
// add a group if a repeat ! // add a group if a repeat !
if (owner instanceof XSElementDeclaration && o.maximum != 1) if (owner instanceof XSElementDeclaration && occurs.maximum != 1)
{ {
final Element groupElement = this.createGroup(xformsDocument, final Element groupElement = this.createGroup(xformsDocument,
modelSection, modelSection,
@@ -1831,8 +1826,8 @@ public class Schema2XForms
modelSection, modelSection,
formSection, formSection,
controlType, controlType,
o, pathToRoot,
pathToRoot); occurs);
// create the form control element // create the form control element
//put a wrapper for the repeat content, but only if it is really a repeat //put a wrapper for the repeat content, but only if it is really a repeat
@@ -1856,7 +1851,7 @@ public class Schema2XForms
owner, owner,
bindId, bindId,
bindElement, bindElement,
o, occurs,
resourceBundle); resourceBundle);
repeatSection.appendChild(formControl); repeatSection.appendChild(formControl);
@@ -1875,27 +1870,6 @@ public class Schema2XForms
return formSection; return formSection;
} }
private Element addSimpleType(final Document xformsDocument,
final Element modelSection,
final Element formSection,
final XSModel schema,
final XSSimpleTypeDefinition controlType,
final XSElementDeclaration owner,
final String pathToRoot,
final ResourceBundle resourceBundle)
{
return this.addSimpleType(xformsDocument,
modelSection,
formSection,
schema,
controlType,
owner.getName(),
owner,
pathToRoot,
SchemaUtil.getOccurance(owner),
resourceBundle);
}
private Element addSimpleType(final Document xformsDocument, private Element addSimpleType(final Document xformsDocument,
final Element modelSection, final Element modelSection,
final Element formSection, final Element formSection,

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.forms.xforms;
import java.io.*;
import java.util.*;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.forms.XMLUtil;
import org.alfresco.util.BaseTest;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
import org.chiba.xml.ns.NamespaceConstants;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* JUnit tests to exercise the the schema to xforms converter
*
* @author ariel backenroth
*/
public class Schema2XFormsTest
extends BaseTest
{
public void testOneStringTestWithEmptyInstanceDocument()
throws Exception
{
final Document schemaDocument = this.loadTestResourceDocument("xforms/unit-tests/automated/one-string-test.xsd");
final Document xformsDocument = this.buildXForm(null, schemaDocument, "one-string-test");
final JXPathContext xpathContext = JXPathContext.newContext(xformsDocument);
Pointer pointer = xpathContext.getPointer("//*[@id='input_0']");
assertNotNull(pointer);
String s = ((Element)pointer.getNode()).getAttributeNS(NamespaceConstants.XFORMS_NS, "bind");
assertNotNull(s);
pointer = xpathContext.getPointer("//*[@id='" + s + "']");
assertNotNull(pointer);
assertEquals("true()", ((Element)pointer.getNode()).getAttributeNS(NamespaceConstants.XFORMS_NS, "required"));
pointer = xpathContext.getPointer("//" + NamespaceConstants.XFORMS_PREFIX + ":instance[@id='instance_0']/one-string-test/string");
assertNotNull(pointer);
assertEquals("default-value", ((Element)pointer.getNode()).getTextContent());
}
public void testOneStringTestWithInstanceDocument()
throws Exception
{
final Document instanceDocument = XMLUtil.parse("<one-string-test><string>test</string></one-string-test>");
final Document schemaDocument = this.loadTestResourceDocument("xforms/unit-tests/automated/one-string-test.xsd");
final Document xformsDocument = this.buildXForm(instanceDocument, schemaDocument, "one-string-test");
final JXPathContext xpathContext = JXPathContext.newContext(xformsDocument);
Pointer pointer = xpathContext.getPointer("//*[@id='input_0']");
assertNotNull(pointer);
String s = ((Element)pointer.getNode()).getAttributeNS(NamespaceConstants.XFORMS_NS, "bind");
pointer = xpathContext.getPointer("//*[@id='" + s + "']");
assertNotNull(pointer);
assertEquals("true()", ((Element)pointer.getNode()).getAttributeNS(NamespaceConstants.XFORMS_NS, "required"));
pointer = xpathContext.getPointer("//" + NamespaceConstants.XFORMS_PREFIX + ":instance[@id='instance_0']/one-string-test/string");
assertNotNull(pointer);
assertEquals("test", ((Element)pointer.getNode()).getTextContent());
}
public void testRepeatConstraintsTest()
throws Exception
{
final Document schemaDocument = this.loadTestResourceDocument("xforms/unit-tests/automated/repeat-constraints-test.xsd");
final Document xformsDocument = this.buildXForm(null, schemaDocument, "repeat-constraints-test");
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/one-to-inf",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/zero-to-inf",
new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/one-to-five",
new SchemaUtil.Occurance(1, 5));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/three-to-five",
new SchemaUtil.Occurance(3, 5));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/zero-to-five",
new SchemaUtil.Occurance(0, 5));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/referenced-string",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-zero-to-inf",
new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-zero-to-inf/nested-zero-to-inf-inner-zero-to-inf",
new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-zero-to-inf/nested-zero-to-inf-inner-one-to-inf",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-one-to-inf",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-one-to-inf/nested-one-to-inf-inner-zero-to-inf",
new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-one-to-inf/nested-one-to-inf-inner-one-to-inf",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-three-to-five",
new SchemaUtil.Occurance(3, 5));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-three-to-five/nested-three-to-five-inner-zero-to-inf",
new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-three-to-five/nested-three-to-five-inner-one-to-inf",
new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-outer-three-to-inf",
new SchemaUtil.Occurance(3, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-outer-three-to-inf/nested-outer-inner-five-to-inf",
new SchemaUtil.Occurance(5, SchemaUtil.Occurance.UNBOUNDED));
this.assertRepeatProperties(xformsDocument,
"/repeat-constraints-test/nested-outer-outer-three-to-inf/nested-outer-inner-five-to-inf/nested-inner-inner-seven-to-inf",
new SchemaUtil.Occurance(7, SchemaUtil.Occurance.UNBOUNDED));
}
private void assertRepeatProperties(final Document xformsDocument, final String nodeset, final SchemaUtil.Occurance o)
{
final Element[] bindElements = this.resolveBind(xformsDocument, nodeset);
assertNotNull("unable to resolve bind for nodeset " + nodeset, bindElements);
assertFalse("unable to resolve bind for nodeset " + nodeset, 0 == bindElements.length);
final Element nodesetBindElement = bindElements[bindElements.length - 1];
assertEquals("unexpected minimum value for nodeset " + nodeset,
o.minimum,
Integer.parseInt(nodesetBindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs")));
if (o.isUnbounded())
{
assertEquals("unexpected maximum value for nodeset " + nodeset,
"unbounded",
nodesetBindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs"));
}
else
{
assertEquals("unexpected maximum value for nodeset " + nodeset,
o.maximum,
Integer.parseInt(nodesetBindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs")));
}
assertEquals("unexpected required value for nodeset " + nodeset,
(o.minimum != 0 && nodesetBindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "type")) + "()",
nodesetBindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "required"));
JXPathContext xpathContext = JXPathContext.newContext(xformsDocument);
String xpath = "//*[@" + NamespaceConstants.XFORMS_PREFIX + ":bind='" + nodesetBindElement.getAttribute("id") + "']";
assertEquals(4, xpathContext.selectNodes(xpath).size());
xpath = ("//" + NamespaceConstants.XFORMS_PREFIX +
":repeat[@" + NamespaceConstants.XFORMS_PREFIX +
":bind='" + nodesetBindElement.getAttribute("id") + "']");
assertEquals(1, xpathContext.selectNodes(xpath).size());
xpath = ("//" + NamespaceConstants.XFORMS_PREFIX +
":trigger[@" + NamespaceConstants.XFORMS_PREFIX +
":bind='" + nodesetBindElement.getAttribute("id") + "']");
assertEquals(3, xpathContext.selectNodes(xpath).size());
int nestingFactor = 1;
for (int i = 0; i < bindElements.length - 1; i++)
{
final SchemaUtil.Occurance parentO = this.occuranceFromBind(bindElements[i]);
if (parentO.isRepeated())
{
nestingFactor = nestingFactor * (1 + parentO.minimum);
}
}
final Pointer instance0 = xpathContext.getPointer("//" + NamespaceConstants.XFORMS_PREFIX + ":instance[@id='instance_0']");
assertNotNull(instance0);
assertNotNull(instance0.getNode());
xpathContext = xpathContext.getRelativeContext(instance0);
xpath = nodeset.substring(1);
assertEquals("unexpected result for instance nodeset " + xpath + " in " + instance0.getNode(),
nestingFactor * (o.minimum + 1),
xpathContext.selectNodes(xpath).size());
xpath = nodeset.substring(1) + "[@" + NamespaceService.ALFRESCO_PREFIX + ":prototype='true']";
assertEquals("unexpected result for instance prototype nodeset " + nodeset + " in " + instance0.getNode(),
nestingFactor,
xpathContext.selectNodes(xpath).size());
}
/**
* Returns the resolved bind and all parents binds for the nodeset.
*/
private Element[] resolveBind(final Document xformsDocument, final String nodeset)
{
JXPathContext xpathContext = JXPathContext.newContext(xformsDocument);
assertNotNull(nodeset);
assertEquals('/', nodeset.charAt(0));
final String rootNodePath = nodeset.replaceFirst("(\\/[^\\/]+).*", "$1");
assertNotNull(rootNodePath);
String xpath = ("//" + NamespaceConstants.XFORMS_PREFIX +
":bind[@" + NamespaceConstants.XFORMS_PREFIX +
":nodeset='" + rootNodePath + "']");
Pointer pointer = xpathContext.getPointer(xpath);
assertNotNull("unable to resolve xpath for root node " + xpath, pointer);
assertNotNull("unable to resolve xpath for root node " + xpath, pointer.getNode());
if (nodeset.equals(rootNodePath))
{
return new Element[] { (Element)pointer.getNode() };
}
xpathContext = xpathContext.getRelativeContext(pointer);
// substring the path to the next slash and split it
final LinkedList<Element> result = new LinkedList<Element>();
result.add((Element)pointer.getNode());
for (String p : nodeset.substring(rootNodePath.length() + 1).split("/"))
{
xpath = NamespaceConstants.XFORMS_PREFIX + ":bind[starts-with(@" + NamespaceConstants.XFORMS_PREFIX + ":nodeset, '" + p + "')]";
pointer = xpathContext.getPointer(xpath);
assertNotNull("unable to resolve path " + xpath +
" on bind with nodeset " + result.getLast().getAttributeNS(NamespaceConstants.XFORMS_NS, "nodeset"),
pointer);
assertNotNull("unable to resolve path " + xpath +
" on bind with nodeset " + result.getLast().getAttributeNS(NamespaceConstants.XFORMS_NS, "nodeset"),
pointer.getNode());
xpathContext = xpathContext.getRelativeContext(pointer);
result.add((Element)pointer.getNode());
}
return (Element[])result.toArray(new Element[result.size()]);
}
private Document loadTestResourceDocument(final String path)
throws IOException, SAXException
{
File f = new File(this.getResourcesDir());
for (final String p : path.split("/"))
{
f = new File(f, p);
}
return XMLUtil.parse(f);
}
private Document buildXForm(final Document instanceDocument,
final Document schemaDocument,
final String rootElementName)
throws FormBuilderException
{
final Schema2XForms s2xf = new Schema2XForms("/test_action",
Schema2XForms.SubmitMethod.POST,
"http://fake.base.url");
return s2xf.buildXForm(instanceDocument,
schemaDocument,
rootElementName,
new ResourceBundle()
{
public Object handleGetObject(final String key)
{
if (key == null)
{
throw new NullPointerException();
}
return null;
}
public Enumeration<String> getKeys()
{
return new Vector<String>().elements();
}
});
}
private SchemaUtil.Occurance occuranceFromBind(final Element bindElement)
{
return new SchemaUtil.Occurance(bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs")
? Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs"))
: 1,
bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs")
? ("unbounded".equals(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs"))
? SchemaUtil.Occurance.UNBOUNDED
: Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs")))
: 1);
}
}

View File

@@ -51,23 +51,14 @@ public class SchemaUtil
public Occurance(final XSParticle particle) public Occurance(final XSParticle particle)
{ {
if (particle == null) this(particle.getMinOccurs(), (particle.getMaxOccursUnbounded()
{ ? Occurance.UNBOUNDED
this.minimum = 1; : particle.getMaxOccurs()));
this.maximum = 1;
}
else
{
this.minimum = particle.getMinOccurs();
this.maximum = (particle.getMaxOccursUnbounded()
? Occurance.UNBOUNDED
: particle.getMaxOccurs());
}
} }
public Occurance(final int minimum) public Occurance(final int minimum)
{ {
this(minimum, UNBOUNDED); this(minimum, Occurance.UNBOUNDED);
} }
public Occurance(final int minimum, final int maximum) public Occurance(final int minimum, final int maximum)
@@ -737,8 +728,7 @@ public class SchemaUtil
//get occurance on encosing element declaration //get occurance on encosing element declaration
final XSParticle particle = final XSParticle particle =
SchemaUtil.findCorrespondingParticleInComplexType(elDecl); SchemaUtil.findCorrespondingParticleInComplexType(elDecl);
final Occurance result = new Occurance(particle); final Occurance result = particle == null ? new Occurance(1, 1) : new Occurance(particle);
if (LOGGER.isDebugEnabled()) if (LOGGER.isDebugEnabled())
{ {
LOGGER.debug("getOccurance for " + elDecl.getName() + LOGGER.debug("getOccurance for " + elDecl.getName() +

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XMLSpy v2007 sp2 (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="title" type="xs:normalizedString"/>
<xs:element name="text" type="xs:string"/>
<xs:element name="picture" type="xs:anyURI"/>
<xs:element name="heading" type="xs:normalizedString"/>
<xs:element name="document">
<xs:complexType>
<xs:sequence>
<xs:element ref="ContentHeadingMain"/>
<xs:element ref="ContentHeading"/>
<xs:element ref="Features"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Features">
<xs:complexType>
<xs:sequence>
<xs:element ref="heading"/>
<xs:element ref="ContentFeature" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ContentHeadingMain">
<xs:complexType>
<xs:attribute name="title" type="xs:normalizedString" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="ContentHeading">
<xs:complexType>
<xs:sequence>
<xs:element ref="title"/>
<xs:element ref="text"/>
<xs:element ref="picture"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ContentFeature">
<xs:complexType>
<xs:sequence>
<xs:element ref="text"/>
<xs:element ref="picture"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="one-string-test">
<xs:complexType>
<xs:sequence>
<xs:element name="string" type="xs:normalizedString" default="default-value"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="referenced-string" type="xs:normalizedString"/>
<xs:element name="repeat-constraints-test">
<xs:complexType>
<xs:sequence>
<xs:element name="zero-to-one" type="xs:normalizedString" minOccurs="0" maxOccurs="1"/>
<xs:element name="one-to-one" type="xs:normalizedString" minOccurs="1" maxOccurs="1"/>
<xs:element name="one-to-inf" type="xs:normalizedString" minOccurs="1" maxOccurs="unbounded"/>
<xs:element name="zero-to-inf" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-five" type="xs:normalizedString" minOccurs="1" maxOccurs="5"/>
<xs:element name="three-to-five" type="xs:normalizedString" minOccurs="3" maxOccurs="5"/>
<xs:element name="zero-to-five" type="xs:normalizedString" minOccurs="0" maxOccurs="5"/>
<xs:element ref="referenced-string" minOccurs="1" maxOccurs="unbounded"/>
<xs:element name="nested-outer-zero-to-inf" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="nested-zero-to-inf-inner-zero-to-inf" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="nested-zero-to-inf-inner-one-to-inf" type="xs:normalizedString" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="nested-outer-one-to-inf" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="nested-one-to-inf-inner-zero-to-inf" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="nested-one-to-inf-inner-one-to-inf" type="xs:normalizedString" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="nested-outer-three-to-five" minOccurs="3" maxOccurs="5">
<xs:complexType>
<xs:sequence>
<xs:element name="nested-three-to-five-inner-zero-to-inf" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="nested-three-to-five-inner-one-to-inf" type="xs:normalizedString" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="nested-outer-outer-three-to-inf" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="nested-outer-outer-string" type="xs:normalizedString" minOccurs="1" maxOccurs="1"/>
<xs:element name="nested-outer-inner-five-to-inf" minOccurs="5" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="nested-outer-inner-string" type="xs:normalizedString" minOccurs="1" maxOccurs="1"/>
<xs:element name="nested-inner-inner-seven-to-inf" type="xs:normalizedString" minOccurs="7" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"> elementFormDefault="qualified">
<xs:element name="simple"> <xs:element name="simple-test">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element name="string" type="xs:normalizedString" default="default string value"/> <xs:element name="string" type="xs:normalizedString" default="default string value"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB