diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java index b05ae6955e..cab7438992 100644 --- a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java @@ -272,7 +272,8 @@ public class Schema2XForms formSection, schema, rootElementDecl, - "/" + getElementName(rootElementDecl, xformsDocument), + "/" + this.getElementName(rootElementDecl, xformsDocument), + new SchemaUtil.Occurance(1, 1), resourceBundle); if (rootGroup.getNodeName() != NamespaceConstants.XFORMS_PREFIX + ":group") { @@ -818,27 +819,6 @@ public class Schema2XForms 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, final Element modelSection, final Element defaultInstanceElement, @@ -973,6 +953,7 @@ public class Schema2XForms final XSComplexTypeDefinition controlType, final XSElementDeclaration owner, String pathToRoot, + final SchemaUtil.Occurance occurs, boolean relative, final boolean checkIfExtension, final ResourceBundle resourceBundle) @@ -1000,13 +981,13 @@ public class Schema2XForms formSection, owner, resourceBundle); - final SchemaUtil.Occurance o = SchemaUtil.getOccurance(owner); +// final SchemaUtil.Occurance o = SchemaUtil.getOccurance(owner); final Element repeatSection = this.addRepeatIfNecessary(xformsDocument, modelSection, groupElement, controlType, - o, - pathToRoot); + pathToRoot, + occurs); if (repeatSection != groupElement) { groupElement.setAttributeNS(NamespaceConstants.XFORMS_NS, @@ -1042,9 +1023,11 @@ public class Schema2XForms modelSection, repeatSection, schema, - (XSSimpleTypeDefinition) base, + (XSSimpleTypeDefinition)base, + owner.getName(), owner, pathToRoot, + occurs, resourceBundle); } else @@ -1132,6 +1115,7 @@ public class Schema2XForms final XSModel schema, final XSElementDeclaration elementDecl, final String pathToRoot, + final SchemaUtil.Occurance occurs, final ResourceBundle resourceBundle) throws FormBuilderException { @@ -1158,22 +1142,26 @@ public class Schema2XForms formSection, schema, (XSSimpleTypeDefinition) controlType, + elementDecl.getName(), elementDecl, pathToRoot, + occurs, resourceBundle); } if (controlType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE && "anyType".equals(controlType.getName())) { - return this.addAnyType(xformsDocument, - modelSection, - formSection, - schema, - (XSComplexTypeDefinition)controlType, - elementDecl, - pathToRoot, - resourceBundle); + return this.addSimpleType(xformsDocument, + modelSection, + formSection, + schema, + (XSComplexTypeDefinition)controlType, + elementDecl.getName(), + elementDecl, + pathToRoot, + occurs, + resourceBundle); } if (controlType.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE) @@ -1237,22 +1225,21 @@ public class Schema2XForms if (!relative) { - LOGGER.debug("addElement: bind is not relative for " - + elementDecl.getName()); + LOGGER.debug("addElement: bind is not relative for " + elementDecl.getName()); } else { - final SchemaUtil.Occurance o = SchemaUtil.getOccurance(elementDecl); +// final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(elementDecl); //create the bind in case it is a repeat LOGGER.debug("Adding empty bind for control " + controlType + " type " + typeName + " nodeset " + pathToRoot + - " occurs " + o); + " occurs " + occurs); // create the element and add it to the model. final Element bindElement = this.createBind(xformsDocument, - pathToRoot + (o.isRepeated() ? "[position() != last()]" : "")); + pathToRoot + (occurs.isRepeated() ? "[position() != last()]" : "")); final String bindId = bindElement.getAttributeNS(null, "id"); modelSection.appendChild(bindElement); @@ -1260,7 +1247,7 @@ public class Schema2XForms schema, controlType, null, - o); + occurs); } return this.addComplexType(xformsDocument, modelSection, @@ -1270,6 +1257,7 @@ public class Schema2XForms (XSComplexTypeDefinition)controlType, elementDecl, pathToRoot, + occurs, true, false, resourceBundle); @@ -1343,6 +1331,7 @@ public class Schema2XForms (XSComplexTypeDefinition)controlType, elementDecl, pathToRoot, + SchemaUtil.getOccurance(elementDecl), true, false, resourceBundle); @@ -1390,6 +1379,7 @@ public class Schema2XForms (XSComplexTypeDefinition) type, elementDecl, pathToRoot, + SchemaUtil.getOccurance(elementDecl), true, true, resourceBundle); @@ -1464,7 +1454,7 @@ public class Schema2XForms final XSComplexTypeDefinition controlType, final XSElementDeclaration owner, final String pathToRoot, - final SchemaUtil.Occurance o, + final SchemaUtil.Occurance occurs, final boolean checkIfExtension, final ResourceBundle resourceBundle) throws FormBuilderException @@ -1478,8 +1468,8 @@ public class Schema2XForms modelSection, formSection, owner.getTypeDefinition(), - o, - pathToRoot); + pathToRoot, + occurs); if (LOGGER.isDebugEnabled()) { @@ -1492,16 +1482,15 @@ public class Schema2XForms { final XSParticle currentNode = (XSParticle)particles.item(counter); XSTerm term = currentNode.getTerm(); - + final SchemaUtil.Occurance childOccurs = new SchemaUtil.Occurance(currentNode); 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 (LOGGER.isDebugEnabled()) { LOGGER.debug(" term is a group"); @@ -1590,6 +1579,7 @@ public class Schema2XForms schema, element, pathToRoot, + childOccurs, resourceBundle); } else @@ -1610,6 +1600,7 @@ public class Schema2XForms schema, element, pathToRoot, + childOccurs, resourceBundle); } } @@ -1634,9 +1625,11 @@ public class Schema2XForms final XSModel schema, final XSElementDeclaration element, final String pathToRoot, + final SchemaUtil.Occurance occurs, final ResourceBundle resourceBundle) throws FormBuilderException { + LOGGER.debug("addElement to group " + element + " at " + pathToRoot); //add it normally final String elementName = this.getElementName(element, xformsDocument); final String path = (pathToRoot.length() == 0 @@ -1657,24 +1650,25 @@ public class Schema2XForms schema, element, path, + occurs, resourceBundle); - final SchemaUtil.Occurance elementOccurs = SchemaUtil.getOccurance(element); - LOGGER.debug("adding " + (elementOccurs.maximum == 1 +// final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(element); + LOGGER.debug("adding " + (occurs.maximum == 1 ? 1 - : elementOccurs.minimum + 1) + + : occurs.minimum + 1) + " default instance element for " + elementName + " at path " + path); // 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 + " 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); - if (i == elementOccurs.minimum) + if (i == occurs.minimum) { e.setAttributeNS(NamespaceService.ALFRESCO_URI, NamespaceService.ALFRESCO_PREFIX + ":prototype", @@ -1687,7 +1681,7 @@ public class Schema2XForms { LOGGER.debug("adding one default instance element for " + elementName + " at path " + path); - if (elementOccurs.minimum == 0) + if (occurs.minimum == 0) { newDefaultInstanceElement.setAttributeNS(NamespaceConstants.XMLSCHEMA_INSTANCE_NS, NamespaceConstants.XMLSCHEMA_INSTANCE_PREFIX + ":nil", @@ -1704,8 +1698,8 @@ public class Schema2XForms final Element modelSection, final Element formSection, 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 @@ -1789,13 +1783,14 @@ public class Schema2XForms final String owningElementName, final XSObject owner, final String pathToRoot, - final SchemaUtil.Occurance o, + final SchemaUtil.Occurance occurs, final ResourceBundle resourceBundle) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("addSimpleType for " + controlType.getName() + - " (owningElementName=" + owningElementName + ")"); + " (owningElementName=" + owningElementName + ")" + + " occurs = " + occurs); if (owner != null) { LOGGER.debug("owner is " + owner.getClass() + @@ -1805,13 +1800,13 @@ public class Schema2XForms // create the element and add it to the model. Element bindElement = - this.createBind(xformsDocument, pathToRoot + (o.isRepeated() ? "[position() != last()]" : "")); + this.createBind(xformsDocument, pathToRoot + (occurs.isRepeated() ? "[position() != last()]" : "")); String bindId = bindElement.getAttributeNS(null, "id"); 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 ! - if (owner instanceof XSElementDeclaration && o.maximum != 1) + if (owner instanceof XSElementDeclaration && occurs.maximum != 1) { final Element groupElement = this.createGroup(xformsDocument, modelSection, @@ -1831,8 +1826,8 @@ public class Schema2XForms modelSection, formSection, controlType, - o, - pathToRoot); + pathToRoot, + occurs); // create the form control element //put a wrapper for the repeat content, but only if it is really a repeat @@ -1856,7 +1851,7 @@ public class Schema2XForms owner, bindId, bindElement, - o, + occurs, resourceBundle); repeatSection.appendChild(formControl); @@ -1875,27 +1870,6 @@ public class Schema2XForms 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, final Element modelSection, final Element formSection, diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java new file mode 100644 index 0000000000..2651cb1f6c --- /dev/null +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java @@ -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("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 result = new LinkedList(); + 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 getKeys() + { + return new Vector().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); + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java index 39038d42d5..1e89a256e6 100644 --- a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java +++ b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java @@ -51,23 +51,14 @@ public class SchemaUtil public Occurance(final XSParticle particle) { - if (particle == null) - { - this.minimum = 1; - this.maximum = 1; - } - else - { - this.minimum = particle.getMinOccurs(); - this.maximum = (particle.getMaxOccursUnbounded() - ? Occurance.UNBOUNDED - : particle.getMaxOccurs()); - } + this(particle.getMinOccurs(), (particle.getMaxOccursUnbounded() + ? Occurance.UNBOUNDED + : particle.getMaxOccurs())); } public Occurance(final int minimum) { - this(minimum, UNBOUNDED); + this(minimum, Occurance.UNBOUNDED); } public Occurance(final int minimum, final int maximum) @@ -737,8 +728,7 @@ public class SchemaUtil //get occurance on encosing element declaration final XSParticle particle = SchemaUtil.findCorrespondingParticleInComplexType(elDecl); - final Occurance result = new Occurance(particle); - + final Occurance result = particle == null ? new Occurance(1, 1) : new Occurance(particle); if (LOGGER.isDebugEnabled()) { LOGGER.debug("getOccurance for " + elDecl.getName() + diff --git a/source/test-resources/xforms/customer-tests/nyronian-1.xsd b/source/test-resources/xforms/customer-tests/nyronian-1.xsd new file mode 100644 index 0000000000..de06462c2b --- /dev/null +++ b/source/test-resources/xforms/customer-tests/nyronian-1.xsd @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/automated/one-string-test.xsd b/source/test-resources/xforms/unit-tests/automated/one-string-test.xsd new file mode 100644 index 0000000000..5781468893 --- /dev/null +++ b/source/test-resources/xforms/unit-tests/automated/one-string-test.xsd @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/automated/repeat-constraints-test.xsd b/source/test-resources/xforms/unit-tests/automated/repeat-constraints-test.xsd new file mode 100644 index 0000000000..07e5c87892 --- /dev/null +++ b/source/test-resources/xforms/unit-tests/automated/repeat-constraints-test.xsd @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/simple-test/simple-test.xsd b/source/test-resources/xforms/unit-tests/simple-test/simple-test.xsd index f105a6ddb1..57c240b012 100644 --- a/source/test-resources/xforms/unit-tests/simple-test/simple-test.xsd +++ b/source/test-resources/xforms/unit-tests/simple-test/simple-test.xsd @@ -1,7 +1,7 @@ - + diff --git a/source/web/images/icons/regenerate_renditions.gif b/source/web/images/icons/regenerate_renditions.gif index f614348cc7..3003358a53 100644 Binary files a/source/web/images/icons/regenerate_renditions.gif and b/source/web/images/icons/regenerate_renditions.gif differ diff --git a/source/web/images/icons/regenerate_renditions_large.gif b/source/web/images/icons/regenerate_renditions_large.gif index 9a06053822..fd4175b85d 100644 Binary files a/source/web/images/icons/regenerate_renditions_large.gif and b/source/web/images/icons/regenerate_renditions_large.gif differ