diff --git a/source/java/org/alfresco/web/bean/ErrorBean.java b/source/java/org/alfresco/web/bean/ErrorBean.java index 8cf9b29244..a7429d264e 100644 --- a/source/java/org/alfresco/web/bean/ErrorBean.java +++ b/source/java/org/alfresco/web/bean/ErrorBean.java @@ -123,7 +123,8 @@ public class ErrorBean { StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); - this.lastError.printStackTrace(writer); + if (this.lastError != null) + this.lastError.printStackTrace(writer); // format the message for HTML display String trace = stringWriter.toString(); diff --git a/source/java/org/alfresco/web/bean/ajax/XFormsBean.java b/source/java/org/alfresco/web/bean/ajax/XFormsBean.java index d596cb69b0..da32bd8dc7 100644 --- a/source/java/org/alfresco/web/bean/ajax/XFormsBean.java +++ b/source/java/org/alfresco/web/bean/ajax/XFormsBean.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.util.Map; import java.util.HashMap; +import java.util.LinkedList; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; @@ -36,7 +37,10 @@ import org.w3c.dom.Node; import org.alfresco.web.app.servlet.FacesHelper; import org.chiba.xml.xforms.ChibaBean; import org.chiba.xml.xforms.exception.XFormsException; +import org.chiba.xml.xforms.events.XFormsEvent; import org.chiba.xml.xforms.events.XFormsEventFactory; + +import org.w3c.dom.*; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; @@ -47,13 +51,13 @@ import org.chiba.xml.xforms.connector.http.AbstractHTTPConnector; * Manages the chiba bean lifecycle. */ public class XFormsBean - implements EventListener { private static final Log LOGGER = LogFactory.getLog(XFormsBean.class); private TemplateType tt; private InstanceData instanceData = null; private ChibaBean chibaBean; + private final LinkedList eventLog = new LinkedList(); /** @return the template type */ public TemplateType getTemplateType() @@ -95,12 +99,33 @@ public class XFormsBean tt.getInputMethods().get(0); final Document form = tim.getXForm(instanceData.getContent(), tt); this.chibaBean.setXMLContainer(form); - this.chibaBean.init(); - EventTarget et = (EventTarget) + + final EventTarget et = (EventTarget) this.chibaBean.getXMLContainer().getDocumentElement(); - //XXXarielb register more listener for to do validation and do something - //with the results. - et.addEventListener(XFormsEventFactory.SUBMIT_ERROR, this, true); + final EventListener el = new EventListener() + { + public void handleEvent(Event e) + { + XFormsBean.LOGGER.debug("received event " + e); + XFormsBean.this.eventLog.add((XFormsEvent)e); + } + }; + // interaction events my occur during init so we have to register before + et.addEventListener(XFormsEventFactory.CHIBA_LOAD_URI, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_RENDER_MESSAGE, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_REPLACE_ALL, el, true); + + this.chibaBean.init(); + + // register for notification events + et.addEventListener(XFormsEventFactory.SUBMIT_ERROR, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_STATE_CHANGED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_PROTOTYPE_CLONED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_ID_GENERATED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_ITEM_INSERTED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_ITEM_DELETED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_INDEX_CHANGED, el, true); + et.addEventListener(XFormsEventFactory.CHIBA_SWITCH_TOGGLED, el, true); } catch (FormBuilderException fbe) { @@ -143,8 +168,34 @@ public class XFormsBean LOGGER.debug(this + " setXFormsValue(" + id + ", " + value + ")"); this.chibaBean.updateControlValue(id, value); + + final TemplatingService ts = TemplatingService.getInstance(); final ResponseWriter out = context.getResponseWriter(); - out.write(""); + ts.writeXML(this.getEventLog(), out); + out.close(); + } + + /** + * sets the value of a control in the processor. + * + * @param id the id of the control in the host document + * @param value the new value + * @return the list of events that may result through this action + */ + public void setRepeatIndex() + throws XFormsException, IOException + { + final FacesContext context = FacesContext.getCurrentInstance(); + final Map requestParameters = context.getExternalContext().getRequestParameterMap(); + final String id = (String)requestParameters.get("id"); + final int index = Integer.parseInt((String)requestParameters.get("index")); + + LOGGER.debug(this + " setRepeatIndex(" + id + ", " + index + ")"); + this.chibaBean.updateRepeatIndex(id, index); + + final TemplatingService ts = TemplatingService.getInstance(); + final ResponseWriter out = context.getResponseWriter(); + ts.writeXML(this.getEventLog(), out); out.close(); } @@ -162,8 +213,10 @@ public class XFormsBean LOGGER.debug(this + " fireAction(" + id + ")"); this.chibaBean.dispatch(id, XFormsEventFactory.DOM_ACTIVATE); + + final TemplatingService ts = TemplatingService.getInstance(); final ResponseWriter out = context.getResponseWriter(); - out.write(""); + ts.writeXML(this.getEventLog(), out); out.close(); } @@ -180,15 +233,38 @@ public class XFormsBean final TemplatingService ts = TemplatingService.getInstance(); final Document result = ts.parseXML(request.getInputStream()); this.instanceData.setContent(result); + final ResponseWriter out = context.getResponseWriter(); ts.writeXML(result, out); out.close(); } - //XXXarielb placeholder for error handling - public void handleEvent(Event e) + private Node getEventLog() { - LOGGER.debug("handleEvent " + e); + final TemplatingService ts = TemplatingService.getInstance(); + final Document result = ts.newDocument(); + final Element eventsElement = result.createElement("events"); + result.appendChild(eventsElement); + for (XFormsEvent xfe : this.eventLog) + { + final String type = xfe.getType(); + final Element target = (Element)xfe.getTarget(); + + final Element eventElement = result.createElement(type); + eventsElement.appendChild(eventElement); + eventElement.setAttribute("targetId", target.getAttributeNS(null, "id")); + eventElement.setAttribute("targetName", target.getLocalName()); + + for (Object name : xfe.getPropertyNames()) + { + final Element propertyElement = result.createElement((String)name); + eventElement.appendChild(propertyElement); + final String value = xfe.getContextInfo((String)name).toString(); + propertyElement.appendChild(result.createTextNode(value)); + } + } + this.eventLog.clear(); + return result; } /** diff --git a/source/java/org/alfresco/web/templating/TemplatingService.java b/source/java/org/alfresco/web/templating/TemplatingService.java index e3fdb432fe..465b0711b7 100644 --- a/source/java/org/alfresco/web/templating/TemplatingService.java +++ b/source/java/org/alfresco/web/templating/TemplatingService.java @@ -308,16 +308,27 @@ public final class TemplatingService { try { - System.out.println("writing out a document for " + n.getNodeName() + - " to " + output); final TransformerFactory tf = TransformerFactory.newInstance(); final Transformer t = tf.newTransformer(); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("writing out a document for " + + (n instanceof Document + ? ((Document)n).getDocumentElement() + : n).getNodeName() + + " to " + output); + final StringWriter sw = new StringWriter(); + t.transform(new DOMSource(n), new StreamResult(sw)); + LOGGER.debug(sw.toString()); + } t.transform(new DOMSource(n), new StreamResult(output)); } catch (TransformerException te) { te.printStackTrace(); - assert false : te.getMessage(); + assert false : te.getMessage(); } } diff --git a/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java b/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java index 6decb71d7a..feaec7b78c 100644 --- a/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java +++ b/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java @@ -145,6 +145,8 @@ public class XFormsInputMethod true); LOGGER.debug("building xform for schema " + tt.getName()); final Document result = builder.buildForm(tt); //schemaFile.getPath()); + LOGGER.debug("generated xform:"); + LOGGER.debug(ts.writeXMLToString(result)); // xmlContentFile.delete(); // schemaFile.delete(); return result; diff --git a/source/java/org/alfresco/web/templating/xforms/schemabuilder/AbstractSchemaFormBuilder.java b/source/java/org/alfresco/web/templating/xforms/schemabuilder/AbstractSchemaFormBuilder.java index ddcd493c59..7b7a2dddd6 100644 --- a/source/java/org/alfresco/web/templating/xforms/schemabuilder/AbstractSchemaFormBuilder.java +++ b/source/java/org/alfresco/web/templating/xforms/schemabuilder/AbstractSchemaFormBuilder.java @@ -455,7 +455,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { //add XMLSchema if we use schema types if (_useSchemaTypes && modelSection != null) modelSection.setAttributeNS(XFORMS_NS, - this.getXFormsNSPrefix() + "schema", + SchemaFormBuilder.XFORMS_NS_PREFIX + "schema", inputURI); //change stylesheet @@ -463,7 +463,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { if (stylesheet != null && stylesheet.length() != 0) envelopeElement.setAttributeNS(CHIBA_NS, - this.getChibaNSPrefix() + "stylesheet", + SchemaFormBuilder.CHIBA_NS_PREFIX + "stylesheet", stylesheet); // TODO: Commented out because comments aren't output properly by the Transformer. @@ -516,7 +516,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { } Element instanceElement = (Element) - modelSection.appendChild(xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "instance")); + modelSection.appendChild(xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "instance")); this.setXFormsId(instanceElement); Element rootElement; @@ -532,9 +532,9 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { instanceElement.appendChild(rootElement); //add XMLSchema instance NS - String prefix = xmlSchemaInstancePrefix.substring(0, xmlSchemaInstancePrefix.length() - 1); + String prefix = XMLSCHEMA_INSTANCE_NS_PREFIX.substring(0, XMLSCHEMA_INSTANCE_NS_PREFIX.length() - 1); if (!rootElement.hasAttributeNS(XMLNS_NAMESPACE_URI, prefix)) - rootElement.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns:" + prefix, XMLSCHEMA_INSTANCE_NAMESPACE_URI); + rootElement.setAttributeNS(XMLNS_NAMESPACE_URI, "xmlns:" + prefix, XMLSCHEMA_INSTANCE_NS); //possibility abandonned for the moment: //modify the instance to add the correct "xsi:type" attributes wherever needed @@ -557,37 +557,37 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { Element submitInfoElement = (Element) modelSection.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "submission")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "submission")); - //submitInfoElement.setAttributeNS(XFORMS_NS,getXFormsNSPrefix()+"id","save"); + //submitInfoElement.setAttributeNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX+"id","save"); String submissionId = this.setXFormsId(submitInfoElement); //action submitInfoElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "action", + SchemaFormBuilder.XFORMS_NS_PREFIX + "action", _action == null ? "" : _action); //method submitInfoElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "method", + SchemaFormBuilder.XFORMS_NS_PREFIX + "method", (_submitMethod != null && _submitMethod.length() != 0 ? _submitMethod : AbstractSchemaFormBuilder.SUBMIT_METHOD_POST)); - //Element submitButton = (Element) formSection.appendChild(xForm.createElementNS(XFORMS_NS,getXFormsNSPrefix()+"submit")); + //Element submitButton = (Element) formSection.appendChild(xForm.createElementNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX+"submit")); Element submitButton = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "submit"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "submit"); Element submitControlWrapper = _wrapper.createControlsWrapper(submitButton); formContentWrapper.appendChild(submitControlWrapper); submitButton.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "submission", + SchemaFormBuilder.XFORMS_NS_PREFIX + "submission", submissionId); this.setXFormsId(submitButton); Element submitButtonCaption = (Element) submitButton.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); submitButtonCaption.appendChild(xForm.createTextNode("Submit")); this.setXFormsId(submitButtonCaption); return xForm; @@ -812,32 +812,27 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { return name; } - /** - * Returns the prefix for the Chiba namespace. - */ - protected String getChibaNSPrefix() { - return chibaNSPrefix; - } - - protected String setXFormsId(Element el) { - //remove the eventuel "id" attribute - if (el.hasAttributeNS(SchemaFormBuilder.XFORMS_NS, "id")) - el.removeAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); - - //long count=this.incIdCounter(); + protected String setXFormsId(final Element el) + { long count = 0; - String name = el.getLocalName(); - Long l = (Long) counter.get(name); + final String name = el.getLocalName(); + final Long l = (Long) counter.get(name); if (l != null) count = l.longValue(); - - String id = name + "_" + count; - //increment the counter counter.put(name, new Long(count + 1)); + + return this.setXFormsId(el, name + "_" + count); + } + + protected String setXFormsId(final Element el, final String id) + { + if (el.hasAttributeNS(SchemaFormBuilder.XFORMS_NS, "id")) + el.removeAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); + el.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - this.getXFormsNSPrefix() + "id", + SchemaFormBuilder.XFORMS_NS_PREFIX + "id", id); return id; } @@ -845,35 +840,21 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { /** * method to set an Id to this element and to all XForms descendants of this element */ - private void resetXFormIds(Element newControl) { - if (newControl.getNamespaceURI() != null - && newControl.getNamespaceURI().equals(XFORMS_NS)) + private void resetXFormIds(Element newControl) + { + if (newControl.getNamespaceURI() != null && + newControl.getNamespaceURI().equals(XFORMS_NS)) this.setXFormsId(newControl); //recursive call - NodeList children = newControl.getChildNodes(); - int nb = children.getLength(); - for (int i = 0; i < nb; i++) { - Node child = children.item(i); + final NodeList children = newControl.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + final Node child = children.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) this.resetXFormIds((Element) child); } } - /** - * Returns the prefix for the XForms namespace. - */ - protected String getXFormsNSPrefix() { - return xformsNSPrefix; - } - - /** - * Returns the prefix for the XLink namespace. - */ - protected String getXLinkNSPrefix() { - return xlinkNSPrefix; - } - /** * __UNDOCUMENTED__ * @@ -897,18 +878,18 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { { String textValue = (String) iterator.next(); Element item = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); this.setXFormsId(item); choicesElement.appendChild(item); Element captionElement = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); this.setXFormsId(captionElement); item.appendChild(captionElement); captionElement.appendChild(xForm.createTextNode(createCaption(textValue))); Element value = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); this.setXFormsId(value); item.appendChild(value); value.appendChild(xForm.createTextNode(textValue)); @@ -951,18 +932,18 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { LOGGER.debug("addChoicesForSelectSwitchControl, processing " + textValue); Element item = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); this.setXFormsId(item); choicesElement.appendChild(item); Element captionElement = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); this.setXFormsId(captionElement); item.appendChild(captionElement); captionElement.appendChild(xForm.createTextNode(createCaption(textValue))); Element value = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); this.setXFormsId(value); item.appendChild(value); value.appendChild(xForm.createTextNode(textValue)); @@ -971,27 +952,29 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { Element action = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "action"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "action"); this.setXFormsId(action); item.appendChild(action); - action.setAttributeNS(XMLEVENTS_NS, xmleventsNSPrefix + "event", "xforms-select"); + action.setAttributeNS(SchemaFormBuilder.XMLEVENTS_NS, + SchemaFormBuilder.XMLEVENTS_NS_PREFIX + "event", + "xforms-select"); - Element toggle = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "toggle"); + Element toggle = xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "toggle"); this.setXFormsId(toggle); //build the case element Element caseElement = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "case"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "case"); String case_id = this.setXFormsId(caseElement); case_types.put(textValue, caseElement); toggle.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "case", + SchemaFormBuilder.XFORMS_NS_PREFIX + "case", case_id); - //toggle.setAttributeNS(XFORMS_NS,getXFormsNSPrefix() + "case",bindIdPrefix + "_" + textValue +"_case"); + //toggle.setAttributeNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX + "case",bindIdPrefix + "_" + textValue +"_case"); action.appendChild(toggle); } } @@ -1005,76 +988,71 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { */ protected Element addHintFromDocumentation(Document xForm, XSAnnotation annotation) { - if (annotation != null) { - Element hintElement = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "hint"); - this.setXFormsId(hintElement); - - Text hintText = - (Text) hintElement.appendChild(xForm.createTextNode("")); - - //write annotation to empty doc - Document doc = DOMUtil.newDocument(true, false); - annotation.writeAnnotation(doc, XSAnnotation.W3C_DOM_DOCUMENT); - - //get "annotation" element - NodeList annots = - doc.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", - "annotation"); - if (annots.getLength() > 0) { - Element annotEl = (Element) annots.item(0); - - //documentation - NodeList docos = - annotEl.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", - "documentation"); - int nbDocos = docos.getLength(); - for (int j = 0; j < nbDocos; j++) { - Element doco = (Element) docos.item(j); - - //get text value - String text = DOMUtil.getTextNodeAsString(doco); - hintText.appendData(text); - - if (j < nbDocos - 1) { - hintText.appendData(" "); - } - } - return hintElement; - } - return null; - } + if (annotation == null) + return null; + Element hintElement = + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "hint"); + this.setXFormsId(hintElement); + + Text hintText = (Text) + hintElement.appendChild(xForm.createTextNode("")); + + //write annotation to empty doc + Document doc = DOMUtil.newDocument(true, false); + annotation.writeAnnotation(doc, XSAnnotation.W3C_DOM_DOCUMENT); + + //get "annotation" element + NodeList annots = doc.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", + "annotation"); + if (annots.getLength() > 0) + { + Element annotEl = (Element) annots.item(0); + + //documentation + NodeList docos = + annotEl.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", + "documentation"); + for (int j = 0; j < docos.getLength(); j++) + { + Element doco = (Element) docos.item(j); + //get text value + String text = DOMUtil.getTextNodeAsString(doco); + hintText.appendData(text); + + if (j < docos.getLength() - 1) + hintText.appendData(" "); + } + return hintElement; + } return null; } - public XSParticle findCorrespondingParticleInComplexType(XSElementDeclaration elDecl) { - XSParticle thisParticle = null; - + public XSParticle findCorrespondingParticleInComplexType(final XSElementDeclaration elDecl) + { XSComplexTypeDefinition complexType = elDecl.getEnclosingCTDefinition(); - if (complexType != null) { - XSParticle particle = complexType.getParticle(); - XSTerm term = particle.getTerm(); - XSObjectList particles; - if (term instanceof XSModelGroup) { - XSModelGroup group = (XSModelGroup) term; - particles = group.getParticles(); - if (particles != null) { - int nb = particles.getLength(); - int i = 0; - while (i < nb && thisParticle == null) { - XSParticle part = (XSParticle) particles.item(i); - //test term - XSTerm thisTerm = part.getTerm(); - if (thisTerm == elDecl) - thisParticle = part; + if (complexType == null) + return null; - i++; - } - } - } + XSParticle particle = complexType.getParticle(); + XSTerm term = particle.getTerm(); + if (! (term instanceof XSModelGroup)) + return null; + + XSModelGroup group = (XSModelGroup) term; + XSObjectList particles = group.getParticles(); + if (particles == null) + return null; + + for (int i = 0; i < particles.getLength(); i++) + { + XSParticle part = (XSParticle) particles.item(i); + //test term + XSTerm thisTerm = part.getTerm(); + if (thisTerm == elDecl) + return part; } - return thisParticle; + return null; } /** @@ -1082,7 +1060,8 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { * * @return a table containing minOccurs and MaxOccurs */ - public Occurs getOccurance(XSElementDeclaration elDecl) { + public Occurs getOccurance(XSElementDeclaration elDecl) + { //get occurance on encosing element declaration XSParticle particle = this.findCorrespondingParticleInComplexType(elDecl); @@ -1121,7 +1100,8 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { if (attrUses != null) { int nbAttr = attrUses.getLength(); - for (int i = 0; i < nbAttr; i++) { + for (int i = 0; i < nbAttr; i++) + { XSAttributeUse currentAttributeUse = (XSAttributeUse)attrUses.item(i); XSAttributeDeclaration currentAttribute = currentAttributeUse.getAttrDeclaration(); @@ -1164,7 +1144,9 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { LOGGER.debug("bindId found: " + bindId); JXPathContext context = JXPathContext.newContext(formSection.getOwnerDocument()); - Pointer pointer = context.getPointer("//*[@" + this.getXFormsNSPrefix() + "bind='" + bindId + "']"); + final Pointer pointer = + context.getPointer("//*[@" + SchemaFormBuilder.XFORMS_NS_PREFIX + + "bind='" + bindId + "']"); if (pointer != null) control = (Element) pointer.getNode(); } @@ -1180,30 +1162,20 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { formSection.appendChild(newControl); } - } else { - String newPathToRoot; - - if (pathToRoot == null || pathToRoot.length() == 0) { - newPathToRoot = "@" + currentAttribute.getName(); - } else if (pathToRoot.endsWith("/")) { - newPathToRoot = - pathToRoot + "@" + currentAttribute.getName(); - } else { - newPathToRoot = - pathToRoot + "/@" + currentAttribute.getName(); - } - - XSSimpleTypeDefinition simpleType = - currentAttribute.getTypeDefinition(); - //TODO SRA: UrType ? - /*if(simpleType==null){ - simpleType=new UrType(); - }*/ + } + else + { + final String newPathToRoot = + (pathToRoot == null || pathToRoot.length() == 0 + ? "@" + currentAttribute.getName() + : (pathToRoot.endsWith("/") + ? pathToRoot + "@" + currentAttribute.getName() + : pathToRoot + "/@" + currentAttribute.getName())); addSimpleType(xForm, modelSection, formSection, - simpleType, + currentAttribute.getTypeDefinition(), currentAttributeUse, newPathToRoot); } @@ -1233,20 +1205,18 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { createGroup(xForm, modelSection, formSection, owner); Element groupWrapper = groupElement; - if (groupElement != modelSection) { + if (groupElement != modelSection) groupWrapper = _wrapper.createGroupContentWrapper(groupElement); - } final Occurs o = this.getOccurance(owner); Element repeatSection = - addRepeatIfNecessary(xForm, - modelSection, - groupWrapper, - controlType, - o, - pathToRoot); + this.addRepeatIfNecessary(xForm, + modelSection, + groupWrapper, + controlType, + o, + pathToRoot); Element repeatContentWrapper = repeatSection; - if (repeatSection != groupWrapper) { @@ -1287,94 +1257,100 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { boolean relative, boolean checkIfExtension) { - if (controlType != null) { + if (controlType == null) + return; - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("addComplexTypeChildren for " + controlType.getName()); - if (owner != null) - LOGGER.debug(" owner=" + owner.getName()); - } - if (controlType.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_MIXED - || (controlType.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE - && controlType.getAttributeUses() != null && controlType.getAttributeUses().getLength() > 0) - ) { - XSTypeDefinition base = controlType.getBaseType(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug(" Control type is mixed . base type=" + base.getName()); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("addComplexTypeChildren for " + controlType.getName()); + if (owner != null) + LOGGER.debug(" owner=" + owner.getName()); + } + if (controlType.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_MIXED || + (controlType.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE && + controlType.getAttributeUses() != null && + controlType.getAttributeUses().getLength() > 0)) + { + XSTypeDefinition base = controlType.getBaseType(); + if (LOGGER.isDebugEnabled()) + LOGGER.debug(" Control type is mixed . base type=" + base.getName()); - if (base != null && base != controlType) { - if (base.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { - addSimpleType(xForm, - modelSection, - formSection, - (XSSimpleTypeDefinition) base, - owner, - pathToRoot); - } else - LOGGER.warn("addComplexTypeChildren for mixed type with basic type complex !"); - } - } else if (LOGGER.isDebugEnabled()) - LOGGER.debug(" Content type = " + controlType.getContentType()); - - - // check for compatible subtypes - // of controlType. - // add a type switch if there are any - // compatible sub-types (i.e. anything - // that derives from controlType) - // add child elements - if (relative) { - pathToRoot = ""; - - //modelSection: find the last element put in the modelSection = bind - modelSection = DOMUtil.getLastChildElement(modelSection); - } - - //attributes - addAttributeSet(xForm, - modelSection, - formSection, - controlType, - owner, - pathToRoot, - checkIfExtension); - - //process group - XSParticle particle = controlType.getParticle(); - if (particle != null) + if (base != null && base != controlType) { - XSTerm term = particle.getTerm(); - if (term instanceof XSModelGroup) + if (base.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug(" Particle of " - + controlType.getName() - + " is a group --->"); - - XSModelGroup group = (XSModelGroup) term; - //call addGroup on this group - this.addGroup(xForm, - modelSection, - formSection, - group, - controlType, - owner, - pathToRoot, - new Occurs(particle), - checkIfExtension); - + addSimpleType(xForm, + modelSection, + formSection, + (XSSimpleTypeDefinition) base, + owner, + pathToRoot); } - else if (LOGGER.isDebugEnabled()) + else + LOGGER.warn("addComplexTypeChildren for mixed type with basic type complex !"); + } + } + else if (LOGGER.isDebugEnabled()) + LOGGER.debug(" Content type = " + controlType.getContentType()); + + + // check for compatible subtypes + // of controlType. + // add a type switch if there are any + // compatible sub-types (i.e. anything + // that derives from controlType) + // add child elements + if (relative) + { + pathToRoot = ""; + + //modelSection: find the last element put in the modelSection = bind + modelSection = DOMUtil.getLastChildElement(modelSection); + } + + //attributes + addAttributeSet(xForm, + modelSection, + formSection, + controlType, + owner, + pathToRoot, + checkIfExtension); + + //process group + XSParticle particle = controlType.getParticle(); + if (particle != null) + { + XSTerm term = particle.getTerm(); + if (term instanceof XSModelGroup) + { + if (LOGGER.isDebugEnabled()) LOGGER.debug(" Particle of " + controlType.getName() - + " is not a group: " - + term.getClass().getName()); - } + + " is a group --->"); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("--->end of addComplexTypeChildren for " - + controlType.getName()); + XSModelGroup group = (XSModelGroup) term; + //call addGroup on this group + this.addGroup(xForm, + modelSection, + formSection, + group, + controlType, + owner, + pathToRoot, + new Occurs(particle), + checkIfExtension); + + } + else if (LOGGER.isDebugEnabled()) + LOGGER.debug(" Particle of " + + controlType.getName() + + " is not a group: " + + term.getClass().getName()); } + + if (LOGGER.isDebugEnabled()) + LOGGER.debug("--->end of addComplexTypeChildren for " + + controlType.getName()); } /** @@ -1400,501 +1376,500 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { return; } - switch (controlType.getTypeCategory()) { - case XSTypeDefinition.SIMPLE_TYPE: - { - addSimpleType(xForm, - modelSection, - formSection, - (XSSimpleTypeDefinition) controlType, - elementDecl, - pathToRoot); + switch (controlType.getTypeCategory()) + { + case XSTypeDefinition.SIMPLE_TYPE: + { + addSimpleType(xForm, + modelSection, + formSection, + (XSSimpleTypeDefinition) controlType, + elementDecl, + pathToRoot); + + break; + } + case XSTypeDefinition.COMPLEX_TYPE: + { + + if (controlType.getName() != null && + controlType.getName().equals("anyType")) + { + addAnyType(xForm, + modelSection, + formSection, + (XSComplexTypeDefinition) controlType, + elementDecl, + pathToRoot); + + break; + } + + // find the types which are compatible(derived from) the parent type. + // + // This is used if we encounter a XML Schema that permits the xsi:type + // attribute to specify subtypes for the element. + // + // For example, the
element may be typed to permit any of + // the following scenarios: + //
+ //
+ //
+ //
+ //
+ //
+ // + // What we want to do is generate an XForm' switch element with cases + // representing any valid non-abstract subtype. + // + // Address + // + // + // US Address Type + // USAddressType + // + // + // + // + // + // Canadian Address Type + // CanadianAddressType + // + // + // + // + // + // International Address Type + // InternationalAddressType + // + // + // + // + // + // + // + // + // validate Address type + // + // + // + // + // + // + // + // + // + // + // + // + // ... + // + // + // + change bindings to add: + // - a bind for the "@xsi:type" attribute + // - for each possible element that can be added through the use of an inheritance, add a "relevant" attribute: + // ex: xforms:relevant="../@xsi:type='USAddress'" + + // look for compatible types + // + String typeName = controlType.getName(); + boolean relative = true; + + if (typeName != null) + { + TreeSet compatibleTypes = (TreeSet) typeTree.get(controlType.getName()); + //TreeSet compatibleTypes = (TreeSet) typeTree.get(controlType); + + if (compatibleTypes != null) + { + relative = false; + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("compatible types for " + + typeName + + ":"); + Iterator it1 = compatibleTypes.iterator(); + while (it1.hasNext()) + { + //String name = (String) it1.next(); + XSTypeDefinition compType = (XSTypeDefinition) it1.next(); + LOGGER.debug(" compatible type name=" + compType.getName()); + } + } + + Element control = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "select1"); + String select1_id = this.setXFormsId(control); + + Element choices = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "choices"); + this.setXFormsId(choices); + + //get possible values + Vector enumValues = new Vector(); + //add the type (if not abstract) + if (!((XSComplexTypeDefinition) controlType).getAbstract()) + enumValues.add(controlType); + //enumValues.add(typeName); + + //add compatible types + Iterator it = compatibleTypes.iterator(); + while (it.hasNext()) + { + enumValues.add(it.next()); + } - break; - } - case XSTypeDefinition.COMPLEX_TYPE: - { + if (enumValues.size() > 1) + { + String caption = + createCaption(elementDecl.getName() + " Type"); + Element controlCaption = + (Element) control.appendChild(xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); + this.setXFormsId(controlCaption); + controlCaption.appendChild(xForm.createTextNode(caption)); + + // multiple compatible types for this element exist + // in the schema - allow the user to choose from + // between compatible non-abstract types + Element bindElement = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind"); + String bindId = + this.setXFormsId(bindElement); + + bindElement.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset", + pathToRoot + "/@xsi:type"); + + modelSection.appendChild(bindElement); + control.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); + + //add the "element" bind, in addition + Element bindElement2 = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind"); + String bindId2 = + this.setXFormsId(bindElement2); + bindElement2.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset", + pathToRoot); + + modelSection.appendChild(bindElement2); + + if (enumValues.size() < Long.parseLong(getProperty(SELECTONE_LONG_LIST_SIZE_PROP))) + { + control.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", + getProperty(SELECTONE_UI_CONTROL_SHORT_PROP)); + } else { + control.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", + getProperty(SELECTONE_UI_CONTROL_LONG_PROP)); + + // add the "Please select..." instruction item for the combobox + // and set the isValid attribute on the bind element to check for the "Please select..." + // item to indicate that is not a valid value + // + String pleaseSelect = + "[Select1 " + caption + "]"; + Element item = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); + this.setXFormsId(item); + choices.appendChild(item); + + Element captionElement = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); + this.setXFormsId(captionElement); + item.appendChild(captionElement); + captionElement.appendChild(xForm.createTextNode(pleaseSelect)); + + Element value = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); + this.setXFormsId(value); + item.appendChild(value); + value.appendChild(xForm.createTextNode(pleaseSelect)); + + // not(purchaseOrder/state = '[Choose State]') + //String isValidExpr = "not(" + bindElement.getAttributeNS(XFORMS_NS, "nodeset") + " = '" + pleaseSelect + "')"; + // ->no, not(. = '[Choose State]') + String isValidExpr = + "not( . = '" + + pleaseSelect + + "')"; + + //check if there was a constraint + String constraint = + bindElement.getAttributeNS(XFORMS_NS, + "constraint"); + + constraint = (constraint != null && constraint.length() != 0 + ? constraint + " && " + isValidExpr + : isValidExpr); + + bindElement.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + + "constraint", + constraint); + } - if (controlType.getName() != null - && controlType.getName().equals("anyType")) { - addAnyType(xForm, - modelSection, - formSection, - (XSComplexTypeDefinition) controlType, - elementDecl, - pathToRoot); + Element choicesControlWrapper = + _wrapper.createControlsWrapper(choices); + control.appendChild(choicesControlWrapper); + + Element controlWrapper = + _wrapper.createControlsWrapper(control); + formSection.appendChild(controlWrapper); + + ///////////////// /////////////// + // add content to select1 + HashMap case_types = new HashMap(); + addChoicesForSelectSwitchControl(xForm, + choices, + enumValues, + case_types); + + ///////////////// + //add a trigger for this control (is there a way to not need it ?) + Element trigger = xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "trigger"); + formSection.appendChild(trigger); + this.setXFormsId(trigger); + Element label_trigger = xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); + this.setXFormsId(label_trigger); + trigger.appendChild(label_trigger); + String trigger_caption = createCaption("validate choice"); + label_trigger.appendChild(xForm.createTextNode(trigger_caption)); + Element action_trigger = xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "action"); + this.setXFormsId(action_trigger); + trigger.appendChild(action_trigger); + Element dispatch_trigger = xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "dispatch"); + this.setXFormsId(dispatch_trigger); + action_trigger.appendChild(dispatch_trigger); + dispatch_trigger.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "name", + "DOMActivate"); + dispatch_trigger.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "target", + select1_id); + + ///////////////// + //add switch + Element switchElement = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "switch"); + this.setXFormsId(switchElement); + + Element switchControlWrapper = + _wrapper.createControlsWrapper(switchElement); + formSection.appendChild(switchControlWrapper); + //formSection.appendChild(switchElement); + + /////////////// add this type ////////////// + Element firstCaseElement = (Element) case_types.get(controlType.getName()); + switchElement.appendChild(firstCaseElement); + addComplexType(xForm, + modelSection, + firstCaseElement, + (XSComplexTypeDefinition) controlType, + elementDecl, + pathToRoot, + true, + false); + + /////////////// add sub types ////////////// + it = compatibleTypes.iterator(); + // add each compatible type within + // a case statement + while (it.hasNext()) { + /*String compatibleTypeName = (String) it.next(); + //WARNING: order of parameters inversed from the doc for 2.6.0 !!! + XSTypeDefinition type =getSchema().getTypeDefinition( + compatibleTypeName, + targetNamespace);*/ + XSTypeDefinition type = (XSTypeDefinition) it.next(); + String compatibleTypeName = type.getName(); + + if (LOGGER.isDebugEnabled()) { + if (type == null) + LOGGER.debug(">>>addElement: compatible type is null!! type=" + + compatibleTypeName + + ", targetNamespace=" + + targetNamespace); + else + LOGGER.debug(" >>>addElement: adding compatible type " + + type.getName()); + } + + if (type != null && + type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) { + + //Element caseElement = (Element) xForm.createElementNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX + "case"); + //caseElement.setAttributeNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX + "id",bindId + "_" + type.getName() +"_case"); + //String case_id=this.setXFormsId(caseElement); + Element caseElement = + (Element) case_types.get(type.getName()); + switchElement.appendChild(caseElement); + + addComplexType(xForm, + modelSection, + caseElement, + (XSComplexTypeDefinition) type, + elementDecl, + pathToRoot, + true, + true); + + ////// + // modify bind to add a "relevant" attribute that checks the value of @xsi:type + // + if (LOGGER.isDebugEnabled()) + DOMUtil.prettyPrintDOM(bindElement2); + NodeList binds = bindElement2.getElementsByTagNameNS(XFORMS_NS, "bind"); + Element thisBind = null; + int nb_binds = binds.getLength(); + int i = 0; + while (i < nb_binds && thisBind == null) + { + Element subBind = (Element) binds.item(i); + String name = subBind.getAttributeNS(XFORMS_NS, "nodeset"); + + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Testing sub-bind with nodeset " + name); + + if (this.isElementDeclaredIn(name, (XSComplexTypeDefinition) type, false) + || this.isAttributeDeclaredIn(name, (XSComplexTypeDefinition) type, false) + ) { + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Element/Attribute " + name + " declared in type " + type.getName() + ": adding relevant attribute"); - break; - } else { + //test sub types of this type + TreeSet subCompatibleTypes = (TreeSet) typeTree.get(type.getName()); + //TreeSet subCompatibleTypes = (TreeSet) typeTree.get(type); + + String newRelevant = null; + if (subCompatibleTypes == null || subCompatibleTypes.isEmpty()) { + //just add ../@xsi:type='type' + newRelevant = "../@xsi:type='" + type.getName() + "'"; + } else { + //add ../@xsi:type='type' or ../@xsi:type='otherType' or ... + newRelevant = "../@xsi:type='" + type.getName() + "'"; + Iterator it_ct = subCompatibleTypes.iterator(); + while (it_ct.hasNext()) { + //String otherTypeName = (String) it_ct.next(); + XSTypeDefinition otherType = (XSTypeDefinition) it_ct.next(); + String otherTypeName = otherType.getName(); + newRelevant = newRelevant + " or ../@xsi:type='" + otherTypeName + "'"; + } + } - // find the types which are compatible(derived from) the parent type. - // - // This is used if we encounter a XML Schema that permits the xsi:type - // attribute to specify subtypes for the element. - // - // For example, the
element may be typed to permit any of - // the following scenarios: - //
- //
- //
- //
- //
- //
- // - // What we want to do is generate an XForm' switch element with cases - // representing any valid non-abstract subtype. - // - // Address - // - // - // US Address Type - // USAddressType - // - // - // - // - // - // Canadian Address Type - // CanadianAddressType - // - // - // - // - // - // International Address Type - // InternationalAddressType - // - // - // - // - // - // - // - // - // validate Address type - // - // - // - // - // - // - // - // - // - // - // - // - // ... - // - // - // + change bindings to add: - // - a bind for the "@xsi:type" attribute - // - for each possible element that can be added through the use of an inheritance, add a "relevant" attribute: - // ex: xforms:relevant="../@xsi:type='USAddress'" + //change relevant attribute + String relevant = subBind.getAttributeNS(XFORMS_NS, "relevant"); + if (relevant != null && relevant.length() != 0) + newRelevant = ("(" + relevant + + ") and " + newRelevant); + if (newRelevant != null && newRelevant.length() != 0) + subBind.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "relevant", + newRelevant); + } - // look for compatible types - // - String typeName = controlType.getName(); - boolean relative = true; + i++; + } + } + } - if (typeName != null) { - TreeSet compatibleTypes = (TreeSet) typeTree.get(controlType.getName()); - //TreeSet compatibleTypes = (TreeSet) typeTree.get(controlType); + /*if (LOGGER.isDebugEnabled()) { + LOGGER.debug( + "###addElement for derived type: bind created:"); + DOMUtil.prettyPrintDOM(bindElement2); + }*/ - if (compatibleTypes != null) { - relative = false; + // we're done + // + break; - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("compatible types for " - + typeName - + ":"); - Iterator it1 = compatibleTypes.iterator(); - while (it1.hasNext()) { - //String name = (String) it1.next(); - XSTypeDefinition compType = (XSTypeDefinition) it1.next(); - LOGGER.debug(" compatible type name=" + compType.getName()); - } - } + } else if (enumValues.size() == 1) { + // only one compatible type, set the controlType value + // and fall through + // + //controlType = getSchema().getComplexType((String)enumValues.get(0)); + controlType = + this.schema.getTypeDefinition((String) enumValues.get(0), + targetNamespace); + } + } else if (LOGGER.isDebugEnabled()) + LOGGER.debug("No compatible type found for " + typeName); - Element control = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "select1"); - String select1_id = this.setXFormsId(control); + //name not null but no compatibleType? + relative = true; + } - Element choices = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "choices"); - this.setXFormsId(choices); + if (relative) //create the bind in case it is a repeat + { + if (LOGGER.isDebugEnabled()) + LOGGER.debug(">>>Adding empty bind for " + typeName); - //get possible values - Vector enumValues = new Vector(); - //add the type (if not abstract) - if (!((XSComplexTypeDefinition) controlType).getAbstract()) - enumValues.add(controlType); - //enumValues.add(typeName); + // create the element and add it to the model. + Element bindElement = + xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind"); + String bindId = this.setXFormsId(bindElement); + bindElement.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset", + pathToRoot); - //add compatible types - Iterator it = compatibleTypes.iterator(); - while (it.hasNext()) { - enumValues.add(it.next()); - } + modelSection.appendChild(bindElement); + } else if (LOGGER.isDebugEnabled()) { + LOGGER.debug("addElement: bind is not relative for " + + elementDecl.getName()); + } - if (enumValues.size() > 1) { - - String caption = - createCaption(elementDecl.getName() + " Type"); - Element controlCaption = - (Element) control.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); - this.setXFormsId(controlCaption); - controlCaption.appendChild(xForm.createTextNode(caption)); - - // multiple compatible types for this element exist - // in the schema - allow the user to choose from - // between compatible non-abstract types - Element bindElement = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "bind"); - String bindId = - this.setXFormsId(bindElement); - - bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "nodeset", - pathToRoot + "/@xsi:type"); - - modelSection.appendChild(bindElement); - control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "bind", - bindId); - - //add the "element" bind, in addition - Element bindElement2 = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "bind"); - String bindId2 = - this.setXFormsId(bindElement2); - bindElement2.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "nodeset", - pathToRoot); - - modelSection.appendChild(bindElement2); - - if (enumValues.size() - < Long.parseLong(getProperty(SELECTONE_LONG_LIST_SIZE_PROP))) { - control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", - getProperty(SELECTONE_UI_CONTROL_SHORT_PROP)); - } else { - control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", - getProperty(SELECTONE_UI_CONTROL_LONG_PROP)); - - // add the "Please select..." instruction item for the combobox - // and set the isValid attribute on the bind element to check for the "Please select..." - // item to indicate that is not a valid value - // - String pleaseSelect = - "[Select1 " + caption + "]"; - Element item = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() - + "item"); - this.setXFormsId(item); - choices.appendChild(item); - - Element captionElement = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() - + "label"); - this.setXFormsId(captionElement); - item.appendChild(captionElement); - captionElement.appendChild(xForm.createTextNode(pleaseSelect)); - - Element value = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() - + "value"); - this.setXFormsId(value); - item.appendChild(value); - value.appendChild(xForm.createTextNode(pleaseSelect)); - - // not(purchaseOrder/state = '[Choose State]') - //String isValidExpr = "not(" + bindElement.getAttributeNS(XFORMS_NS, "nodeset") + " = '" + pleaseSelect + "')"; - // ->no, not(. = '[Choose State]') - String isValidExpr = - "not( . = '" - + pleaseSelect - + "')"; - - //check if there was a constraint - String constraint = - bindElement.getAttributeNS(XFORMS_NS, - "constraint"); - - if ((constraint != null) - && !constraint.equals("")) { - constraint = - constraint - + " && " - + isValidExpr; - } else { - constraint = isValidExpr; - } - - bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() - + "constraint", - constraint); - } - - Element choicesControlWrapper = - _wrapper.createControlsWrapper(choices); - control.appendChild(choicesControlWrapper); - - Element controlWrapper = - _wrapper.createControlsWrapper(control); - formSection.appendChild(controlWrapper); - - ///////////////// /////////////// - // add content to select1 - HashMap case_types = new HashMap(); - addChoicesForSelectSwitchControl(xForm, - choices, - enumValues, - case_types); - - ///////////////// - //add a trigger for this control (is there a way to not need it ?) - Element trigger = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "trigger"); - formSection.appendChild(trigger); - this.setXFormsId(trigger); - Element label_trigger = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label"); - this.setXFormsId(label_trigger); - trigger.appendChild(label_trigger); - String trigger_caption = createCaption("validate choice"); - label_trigger.appendChild(xForm.createTextNode(trigger_caption)); - Element action_trigger = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "action"); - this.setXFormsId(action_trigger); - trigger.appendChild(action_trigger); - Element dispatch_trigger = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "dispatch"); - this.setXFormsId(dispatch_trigger); - action_trigger.appendChild(dispatch_trigger); - dispatch_trigger.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "name", - "DOMActivate"); - dispatch_trigger.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "target", - select1_id); - - ///////////////// - //add switch - Element switchElement = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "switch"); - this.setXFormsId(switchElement); - - Element switchControlWrapper = - _wrapper.createControlsWrapper(switchElement); - formSection.appendChild(switchControlWrapper); - //formSection.appendChild(switchElement); - - /////////////// add this type ////////////// - Element firstCaseElement = (Element) case_types.get(controlType.getName()); - switchElement.appendChild(firstCaseElement); - addComplexType(xForm, - modelSection, - firstCaseElement, - (XSComplexTypeDefinition) controlType, - elementDecl, - pathToRoot, - true, - false); - - /////////////// add sub types ////////////// - it = compatibleTypes.iterator(); - // add each compatible type within - // a case statement - while (it.hasNext()) { - /*String compatibleTypeName = (String) it.next(); - //WARNING: order of parameters inversed from the doc for 2.6.0 !!! - XSTypeDefinition type =getSchema().getTypeDefinition( - compatibleTypeName, - targetNamespace);*/ - XSTypeDefinition type = (XSTypeDefinition) it.next(); - String compatibleTypeName = type.getName(); - - if (LOGGER.isDebugEnabled()) { - if (type == null) - LOGGER.debug(">>>addElement: compatible type is null!! type=" - + compatibleTypeName - + ", targetNamespace=" - + targetNamespace); - else - LOGGER.debug(" >>>addElement: adding compatible type " - + type.getName()); - } - - if (type != null - && type.getTypeCategory() - == XSTypeDefinition - .COMPLEX_TYPE) { - - //Element caseElement = (Element) xForm.createElementNS(XFORMS_NS,getXFormsNSPrefix() + "case"); - //caseElement.setAttributeNS(XFORMS_NS,getXFormsNSPrefix() + "id",bindId + "_" + type.getName() +"_case"); - //String case_id=this.setXFormsId(caseElement); - Element caseElement = - (Element) case_types.get(type.getName()); - switchElement.appendChild(caseElement); - - addComplexType(xForm, - modelSection, - caseElement, - (XSComplexTypeDefinition) type, - elementDecl, - pathToRoot, - true, - true); - - ////// - // modify bind to add a "relevant" attribute that checks the value of @xsi:type - // - if (LOGGER.isDebugEnabled()) - DOMUtil.prettyPrintDOM(bindElement2); - NodeList binds = bindElement2.getElementsByTagNameNS(XFORMS_NS, "bind"); - Element thisBind = null; - int nb_binds = binds.getLength(); - int i = 0; - while (i < nb_binds && thisBind == null) { - Element subBind = (Element) binds.item(i); - String name = subBind.getAttributeNS(XFORMS_NS, "nodeset"); - - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Testing sub-bind with nodeset " + name); - - if (this.isElementDeclaredIn(name, (XSComplexTypeDefinition) type, false) - || this.isAttributeDeclaredIn(name, (XSComplexTypeDefinition) type, false) - ) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("Element/Attribute " + name + " declared in type " + type.getName() + ": adding relevant attribute"); - - //test sub types of this type - TreeSet subCompatibleTypes = (TreeSet) typeTree.get(type.getName()); - //TreeSet subCompatibleTypes = (TreeSet) typeTree.get(type); - - String newRelevant = null; - if (subCompatibleTypes == null || subCompatibleTypes.isEmpty()) { - //just add ../@xsi:type='type' - newRelevant = "../@xsi:type='" + type.getName() + "'"; - } else { - //add ../@xsi:type='type' or ../@xsi:type='otherType' or ... - newRelevant = "../@xsi:type='" + type.getName() + "'"; - Iterator it_ct = subCompatibleTypes.iterator(); - while (it_ct.hasNext()) { - //String otherTypeName = (String) it_ct.next(); - XSTypeDefinition otherType = (XSTypeDefinition) it_ct.next(); - String otherTypeName = otherType.getName(); - newRelevant = newRelevant + " or ../@xsi:type='" + otherTypeName + "'"; - } - } - - //change relevant attribute - String relevant = subBind.getAttributeNS(XFORMS_NS, "relevant"); - if (relevant != null && !relevant.equals("")) { - newRelevant = "(" + relevant + ") and " + newRelevant; - } - if (newRelevant != null && !newRelevant.equals("")) - subBind.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "relevant", newRelevant); - } - - i++; - } - } - } - - /*if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "###addElement for derived type: bind created:"); - DOMUtil.prettyPrintDOM(bindElement2); - }*/ - - // we're done - // - break; - - } else if (enumValues.size() == 1) { - // only one compatible type, set the controlType value - // and fall through - // - //controlType = getSchema().getComplexType((String)enumValues.get(0)); - controlType = - this.schema.getTypeDefinition((String) enumValues.get(0), - targetNamespace); - } - } else if (LOGGER.isDebugEnabled()) - LOGGER.debug("No compatible type found for " + typeName); - - //name not null but no compatibleType? - relative = true; - } - - if (relative) //create the bind in case it is a repeat - { - if (LOGGER.isDebugEnabled()) - LOGGER.debug(">>>Adding empty bind for " + typeName); - - // create the element and add it to the model. - Element bindElement = - xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "bind"); - String bindId = this.setXFormsId(bindElement); - bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "nodeset", - pathToRoot); - - modelSection.appendChild(bindElement); - } else if (LOGGER.isDebugEnabled()) { - LOGGER.debug("addElement: bind is not relative for " - + elementDecl.getName()); - } - - //addComplexType(xForm,modelSection, formSection,(ComplexType)controlType,elementDecl,pathToRoot, relative); - addComplexType(xForm, - modelSection, - formSection, - (XSComplexTypeDefinition) controlType, - elementDecl, - pathToRoot, - true, - false); - - break; - } - } - - default : // TODO: add wildcard support - LOGGER.warn("\nWARNING!!! - Unsupported type [" - + elementDecl.getType() - + "] for node [" - + controlType.getName() - + "]"); - } + //addComplexType(xForm,modelSection, formSection,(ComplexType)controlType,elementDecl,pathToRoot, relative); + addComplexType(xForm, + modelSection, + formSection, + (XSComplexTypeDefinition) controlType, + elementDecl, + pathToRoot, + true, + false); + + break; + } + + default : // TODO: add wildcard support + LOGGER.warn("\nWARNING!!! - Unsupported type [" + + elementDecl.getType() + + "] for node [" + + controlType.getName() + + "]"); + } } - + /** * check that the element defined by this name is declared directly in the type */ - private boolean isElementDeclaredIn(String name, XSComplexTypeDefinition type, boolean recursive) { + private boolean isElementDeclaredIn(String name, XSComplexTypeDefinition type, boolean recursive) + { boolean found = false; if (LOGGER.isDebugEnabled()) LOGGER.debug("isElement " + name + " declared in " + type.getName()); -//test if extension + declared in parent + not recursive -> NOK + //test if extension + declared in parent + not recursive -> NOK if (!recursive && type.getDerivationMethod() == XSConstants.DERIVATION_EXTENSION) { XSComplexTypeDefinition parent = (XSComplexTypeDefinition) type.getBaseType(); if (LOGGER.isDebugEnabled()) @@ -2044,7 +2019,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { XSAttributeUse anAttr = (XSAttributeUse) attrs.item(i); if (anAttr != null) { String name = anAttr.getName(); - if (name == null || name.equals("")) + if (name == null || name.length() == 0) name = anAttr.getAttrDeclaration().getName(); if (attrName.equals(name)) found = true; @@ -2105,12 +2080,12 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { { Element repeatSection = - addRepeatIfNecessary(xForm, - modelSection, - formSection, - owner.getTypeDefinition(), - o, - pathToRoot); + this.addRepeatIfNecessary(xForm, + modelSection, + formSection, + owner.getTypeDefinition(), + o, + pathToRoot); Element repeatContentWrapper = repeatSection; if (repeatSection != formSection) { @@ -2186,8 +2161,11 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { if (LOGGER.isDebugEnabled()) LOGGER.debug("bindId found: " + bindId); - JXPathContext context = JXPathContext.newContext(formSection.getOwnerDocument()); - Pointer pointer = context.getPointer("//*[@" + this.getXFormsNSPrefix() + "bind='" + bindId + "']"); + final JXPathContext context = + JXPathContext.newContext(formSection.getOwnerDocument()); + final Pointer pointer = + context.getPointer("//*[@" + SchemaFormBuilder.XFORMS_NS_PREFIX + + "bind='" + bindId + "']"); if (pointer != null) control = (Element) pointer.getNode(); } @@ -2203,21 +2181,21 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { repeatContentWrapper.appendChild(newControl); } - } else { //add it normally - String elementName = getElementName(element, xForm); + } + else + { //add it normally + final String elementName = getElementName(element, xForm); - String path = pathToRoot + "/" + elementName; - - if (pathToRoot.equals("")) { //relative - path = elementName; - } - - addElement(xForm, - modelSection, - repeatContentWrapper, - element, - element.getTypeDefinition(), - path); + final String path = (pathToRoot.length() == 0 + ? elementName + : pathToRoot + "/" + elementName); + + this.addElement(xForm, + modelSection, + repeatContentWrapper, + element, + element.getTypeDefinition(), + path); } } else { //XSWildcard -> ignore ? //LOGGER.warn("XSWildcard found in group from "+owner.getName()+" for pathToRoot="+pathToRoot); @@ -2238,79 +2216,76 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { XSTypeDefinition controlType, final Occurs o , String pathToRoot) { - Element repeatSection = formSection; // add xforms:repeat section if this element re-occurs // - if (o.maximum != 1) + if (o.maximum == 1) + return formSection; + + if (LOGGER.isDebugEnabled()) + LOGGER.debug("DEBUG: AddRepeatIfNecessary for multiple element for type " + + controlType.getName() + + ", maxOccurs=" + o.maximum); + + final Element repeatSection = + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "repeat"); + + //bind instead of repeat + //repeatSection.setAttributeNS(XFORMS_NS,SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset",pathToRoot); + // bind -> last element in the modelSection + Element bind = DOMUtil.getLastChildElement(modelSection); + String bindId = null; + + if (bind != null && + bind.getLocalName() != null && + "bind".equals(bind.getLocalName())) + bindId = bind.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); + else { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("DEBUG: AddRepeatIfNecessary for multiple element for type " - + controlType.getName() - + ", maxOccurs=" + o.maximum); + LOGGER.warn("addRepeatIfNecessary: bind not found: " + + bind + + " (model selection name=" + + modelSection.getNodeName() + + ")"); - //repeatSection = (Element) formSection.appendChild(xForm.createElementNS(XFORMS_NS,getXFormsNSPrefix() + "repeat")); - repeatSection = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "repeat"); + //if no bind is found -> modelSection is already a bind, get its parent last child + bind = DOMUtil.getLastChildElement(modelSection.getParentNode()); - //bind instead of repeat - //repeatSection.setAttributeNS(XFORMS_NS,getXFormsNSPrefix() + "nodeset",pathToRoot); - // bind -> last element in the modelSection - Element bind = DOMUtil.getLastChildElement(modelSection); - String bindId = null; - - if (bind != null && + if (bind != null && bind.getLocalName() != null && - "bind".equals(bind.getLocalName())) { - bindId = bind.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); - } else { - LOGGER.warn("addRepeatIfNecessary: bind not found: " - + bind - + " (model selection name=" - + modelSection.getNodeName() - + ")"); + "bind".equals(bind.getLocalName())) + bindId = bind.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); + else + LOGGER.warn("addRepeatIfNecessary: bind really not found"); + } - //if no bind is found -> modelSection is already a bind, get its parent last child - bind = DOMUtil.getLastChildElement(modelSection.getParentNode()); + repeatSection.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); + this.setXFormsId(repeatSection); - if (bind != null && - bind.getLocalName() != null && - "bind".equals(bind.getLocalName())) { - bindId = bind.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); - } else { - LOGGER.warn("addRepeatIfNecessary: bind really not found"); - } - } + //appearance=full is more user friendly + repeatSection.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", + "full"); - repeatSection.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "bind", - bindId); - this.setXFormsId(repeatSection); - - //appearance=full is more user friendly - repeatSection.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", - "full"); - - //triggers - this.addTriggersForRepeat(xForm, - formSection, - repeatSection, - o, - bindId); + //triggers + this.addTriggersForRepeat(xForm, + formSection, + repeatSection, + o, + bindId); - Element controlWrapper = - _wrapper.createControlsWrapper(repeatSection); - formSection.appendChild(controlWrapper); - - //add a group inside the repeat? - Element group = xForm.createElementNS(XFORMS_NS, - this.getXFormsNSPrefix() + "group"); - this.setXFormsId(group); - repeatSection.appendChild(group); - repeatSection = group; - } + final Element controlWrapper = + _wrapper.createControlsWrapper(repeatSection); + formSection.appendChild(controlWrapper); + //add a group inside the repeat? + // Element group = xForm.createElementNS(XFORMS_NS, + //this.SchemaFormBuilder.XFORMS_NS_PREFIX + "group"); + //this.setXFormsId(group); + //repeatSection.appendChild(group); + //repeatSection = group; return repeatSection; } @@ -2332,10 +2307,10 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { " (owningElementName=" + owningElementName + ")"); // create the element and add it to the model. - Element bindElement = xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "bind"); + Element bindElement = xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "bind"); String bindId = this.setXFormsId(bindElement); bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "nodeset", + SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset", pathToRoot); bindElement = (Element) modelSection.appendChild(bindElement); bindElement = startBindElement(bindElement, controlType, o); @@ -2371,10 +2346,10 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { //if there is a repeat -> create another bind with "." Element bindElement2 = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "bind"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "bind"); String bindId2 = this.setXFormsId(bindElement2); bindElement2.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "nodeset", + SchemaFormBuilder.XFORMS_NS_PREFIX + "nodeset", "."); bindElement.appendChild(bindElement2); bindId = bindId2; @@ -2396,7 +2371,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { if (!repeatSection.equals(formSection)) { formControl.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "ref", + SchemaFormBuilder.XFORMS_NS_PREFIX + "ref", "."); } @@ -2446,245 +2421,252 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { new Occurs(owningAttribute.getRequired() ? 1 : 0, 1)); } + private Element createTriggerForRepeat(final Document xForm, + final String label, + final Element action) + { + final Element trigger = + xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "trigger"); + this.setXFormsId(trigger); + + //label insert + final Element triggerLabel = + xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); + this.setXFormsId(triggerLabel); + trigger.appendChild(triggerLabel); + //triggerLabel_insert.setAttributeNS(SchemaFormBuilder.XLINK_NS, + // SchemaFormBuilder.XLINK_NS_PREFIX + "href", + // "images/add_new.gif"); + + triggerLabel.appendChild(xForm.createTextNode(label)); + + //hint insert + //Element hint_insert = + // xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + // SchemaFormBuilder.XFORMS_NS_PREFIX + "hint"); + //this.setXFormsId(hint_insert); + //Text hint_insert_text = + // xForm.createTextNode("inserts a new entry in this collection"); + //hint_insert.appendChild(hint_insert_text); + //trigger_insert.appendChild(hint_insert); + + //insert action + final Element actionWrapper = + xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "action"); + actionWrapper.appendChild(action); + trigger.appendChild(action); + this.setXFormsId(action); + + return trigger; + } + + /** * add triggers to use the repeat elements (allow to add an element, ...) */ - private void addTriggersForRepeat(Document xForm, - Element formSection, - Element repeatSection, - Occurs o, - String bindId) { + private void addTriggersForRepeat(final Document xForm, + final Element formSection, + final Element repeatSection, + final Occurs o, + final String bindId) { + //xforms:at = xforms:index from the "id" attribute on the repeat element + final String repeatId = + repeatSection.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); + ///////////// insert ////////////////// //trigger insert - Element trigger_insert = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "trigger"); - this.setXFormsId(trigger_insert); - //label insert - Element triggerLabel_insert = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "label"); - this.setXFormsId(triggerLabel_insert); - trigger_insert.appendChild(triggerLabel_insert); - triggerLabel_insert.setAttributeNS(SchemaFormBuilder.XLINK_NS, - SchemaFormBuilder.xlinkNSPrefix + "href", - "images/add_new.gif"); - - Text label_insert = xForm.createTextNode("Insert after selected"); - triggerLabel_insert.appendChild(label_insert); - - //hint insert - Element hint_insert = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "hint"); - this.setXFormsId(hint_insert); - Text hint_insert_text = - xForm.createTextNode("inserts a new entry in this collection"); - hint_insert.appendChild(hint_insert_text); - trigger_insert.appendChild(hint_insert); - - //insert action - Element action_insert = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "action"); - trigger_insert.appendChild(action_insert); - this.setXFormsId(action_insert); - - Element insert = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "insert"); - action_insert.appendChild(insert); - this.setXFormsId(insert); + Element action = + xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "insert"); + this.setXFormsId(action); //insert: bind & other attributes - if (bindId != null) { - insert.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "bind", - bindId); - } + if (bindId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); - insert.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "position", - "after"); + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "position", + "before"); - //xforms:at = xforms:index from the "id" attribute on the repeat element - String repeatId = - repeatSection.getAttributeNS(SchemaFormBuilder.XFORMS_NS, "id"); + if (repeatId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "at", + "1"); - if (repeatId != null) { - insert.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "at", - SchemaFormBuilder.xformsNSPrefix + "index('" + repeatId + "')"); - } + final Element trigger_insert_before = + this.createTriggerForRepeat(xForm, "insert at beginning", action); + + + action = xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "insert"); + this.setXFormsId(action); + + //insert: bind & other attributes + if (bindId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); + + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "position", + "after"); + + if (repeatId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "at", + SchemaFormBuilder.XFORMS_NS_PREFIX + "index('" + repeatId + "')"); + + final Element trigger_insert_after = + this.createTriggerForRepeat(xForm, "insert after selected", action); ///////////// delete ////////////////// //trigger delete - Element trigger_delete = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "trigger"); - this.setXFormsId(trigger_delete); - - //label delete - Element triggerLabel_delete = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "label"); - this.setXFormsId(triggerLabel_delete); - trigger_delete.appendChild(triggerLabel_delete); - triggerLabel_delete.setAttributeNS(SchemaFormBuilder.XLINK_NS, - SchemaFormBuilder.xlinkNSPrefix + "href", - "images/delete.gif"); - - Text label_delete = xForm.createTextNode("Delete selected"); - triggerLabel_delete.appendChild(label_delete); - - //hint delete - Element hint_delete = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "hint"); - this.setXFormsId(hint_delete); - Text hint_delete_text = - xForm.createTextNode("deletes selected entry from this collection"); - hint_delete.appendChild(hint_delete_text); - trigger_delete.appendChild(hint_delete); - - //delete action - Element action_delete = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "action"); - trigger_delete.appendChild(action_delete); - this.setXFormsId(action_delete); - - Element delete = - xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "delete"); - action_delete.appendChild(delete); - this.setXFormsId(delete); + action = xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "delete"); + this.setXFormsId(action); //delete: bind & other attributes - if (bindId != null) { - delete.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "bind", - bindId); - } + if (bindId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); //xforms:at = xforms:index from the "id" attribute on the repeat element - if (repeatId != null) { - delete.setAttributeNS(SchemaFormBuilder.XFORMS_NS, - SchemaFormBuilder.xformsNSPrefix + "at", - SchemaFormBuilder.xformsNSPrefix + "index('" + repeatId + "')"); - } + if (repeatId != null) + action.setAttributeNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "at", + SchemaFormBuilder.XFORMS_NS_PREFIX + "index('" + repeatId + "')"); + + final Element trigger_delete = + this.createTriggerForRepeat(xForm, "delete selected", action); + //add the triggers - Element wrapper_triggers = - _wrapper.createControlsWrapper(trigger_insert); + final Element wrapper_triggers = + _wrapper.createControlsWrapper(trigger_insert_before); - if (wrapper_triggers == trigger_insert) { //no wrapper - formSection.appendChild(trigger_insert); + if (wrapper_triggers == trigger_insert_after) + { + //no wrapper + formSection.appendChild(trigger_insert_before); + formSection.appendChild(trigger_insert_after); formSection.appendChild(trigger_delete); - } else { + } + else + { formSection.appendChild(wrapper_triggers); + final Element insert_parent = (Element)trigger_insert_before.getParentNode(); - Element insert_parent = (Element) trigger_insert.getParentNode(); - - if (insert_parent != null) { + if (insert_parent != null) + { + insert_parent.appendChild(trigger_insert_before); insert_parent.appendChild(trigger_delete); - } + } } } - private void buildTypeTree(XSTypeDefinition type, TreeSet descendents) { - if (type != null) { + private void buildTypeTree(XSTypeDefinition type, TreeSet descendents) + { + if (type == null) + return; - if (descendents.size() > 0) { - //TreeSet compatibleTypes = (TreeSet) typeTree.get(type.getName()); - TreeSet compatibleTypes = (TreeSet) typeTree.get(type.getName()); - - if (compatibleTypes == null) { - //compatibleTypes = new TreeSet(descendents); - compatibleTypes = new TreeSet(this.typeExtensionSorter); - compatibleTypes.addAll(descendents); - //typeTree.put(type.getName(), compatibleTypes); - typeTree.put(type.getName(), compatibleTypes); - } else { - compatibleTypes.addAll(descendents); - } - } - - XSTypeDefinition parentType = type.getBaseType(); - - if (parentType != null - && type.getTypeCategory() == parentType.getTypeCategory()) { - /*String typeName = type.getName(); - String parentTypeName = parentType.getName(); - if ((typeName == null && parentTypeName != null) - || (typeName != null && parentTypeName == null) - || (typeName != null - && parentTypeName != null - && !type.getName().equals(parentType.getName()) - && !parentType.getName().equals("anyType"))) {*/ - if (type != parentType - && (parentType.getName() == null - || !parentType.getName().equals("anyType"))) { - - //TreeSet newDescendents=new TreeSet(descendents); - TreeSet newDescendents = new TreeSet(this.typeExtensionSorter); - newDescendents.addAll(descendents); + if (descendents.size() > 0) + { + //TreeSet compatibleTypes = (TreeSet) typeTree.get(type.getName()); + TreeSet compatibleTypes = (TreeSet) typeTree.get(type.getName()); + + if (compatibleTypes == null) + { + //compatibleTypes = new TreeSet(descendents); + compatibleTypes = new TreeSet(this.typeExtensionSorter); + compatibleTypes.addAll(descendents); + //typeTree.put(type.getName(), compatibleTypes); + typeTree.put(type.getName(), compatibleTypes); + } + else + { + compatibleTypes.addAll(descendents); + } + } + XSTypeDefinition parentType = type.getBaseType(); + + if (parentType != null && + type.getTypeCategory() == parentType.getTypeCategory()) + { + if (type != parentType && + (parentType.getName() == null || !parentType.getName().equals("anyType"))) + { + + //TreeSet newDescendents=new TreeSet(descendents); + TreeSet newDescendents = new TreeSet(this.typeExtensionSorter); + newDescendents.addAll(descendents); + //extension (we only add it to "newDescendants" because we don't want //to have a type descendant to itself, but to consider it for the parent - if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) { - XSComplexTypeDefinition complexType = - (XSComplexTypeDefinition) type; - if (complexType.getDerivationMethod() - == XSConstants.DERIVATION_EXTENSION - && !complexType.getAbstract() - && !descendents.contains(type) //to be tested + if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) + { + XSComplexTypeDefinition complexType = + (XSComplexTypeDefinition) type; + if (complexType.getDerivationMethod() == XSConstants.DERIVATION_EXTENSION + && !complexType.getAbstract() + && !descendents.contains(type) //to be tested //&& !descendents.contains(type.getName()) //to be tested - ) { + ) + { //newDescendents.add(type.getName()); - newDescendents.add(type); - } - } + newDescendents.add(type); + } + } //note: extensions are impossible on simpleTypes ! - buildTypeTree(parentType, newDescendents); - } - } + buildTypeTree(parentType, newDescendents); + } } } - private void buildTypeTree(XSModel schema) { + private void buildTypeTree(XSModel schema) + { // build the type tree for complex types - // XSNamedMap types = schema.getComponents(XSConstants.TYPE_DEFINITION); - int nb = types.getLength(); - for (int i = 0; i < nb; i++) { + for (int i = 0; i < types.getLength(); i++) + { XSTypeDefinition t = (XSTypeDefinition) types.item(i); - if (t.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) { + if (t.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) + { XSComplexTypeDefinition type = (XSComplexTypeDefinition) t; buildTypeTree(type, new TreeSet(this.typeExtensionSorter)); } } // build the type tree for simple types - for (int i = 0; i < nb; i++) { + for (int i = 0; i < types.getLength(); i++) { XSTypeDefinition t = (XSTypeDefinition) types.item(i); - if (t.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { + if (t.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) + { XSSimpleTypeDefinition type = (XSSimpleTypeDefinition) t; buildTypeTree(type, new TreeSet(this.typeExtensionSorter)); } } // print out type hierarchy for debugging purposes - if (LOGGER.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) + { Iterator keys = typeTree.keySet().iterator(); - while (keys.hasNext()) { + while (keys.hasNext()) + { String typeName = (String) keys.next(); TreeSet descendents = (TreeSet) typeTree.get(typeName); LOGGER.debug(">>>> for " + typeName + " Descendants=\n "); Iterator it = descendents.iterator(); - while (it.hasNext()) { + while (it.hasNext()) + { XSTypeDefinition desc = (XSTypeDefinition) it.next(); LOGGER.debug(" " + desc.getName()); } @@ -2697,7 +2679,8 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { XSTypeDefinition controlType, String bindId, Element bindElement, - Occurs o) { + Occurs o) + { // Select1 xform control to use: // Will use one of the following: input, textarea, selectOne, selectBoolean, selectMany, range // secret, output, button, do not apply @@ -2710,39 +2693,34 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { // Element formControl = null; - if (controlType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { + if (controlType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) + { XSSimpleTypeDefinition simpleType = (XSSimpleTypeDefinition) controlType; if (simpleType.getItemType() != null) //list { - formControl = - createControlForListType(xForm, - simpleType, - caption, - bindElement); - } else { //other simple type + formControl = createControlForListType(xForm, + simpleType, + caption, + bindElement); + } + else + { + //other simple type // need to check constraints to determine which form control to use // // use the selectOne control // - //XSObjectList enumerationFacets = simpleType.getFacets(XSSimpleTypeDefinition.FACET_ENUMERATION); - //if(enumerationFacets.getLength()>0){ - if (simpleType - .isDefinedFacet(XSSimpleTypeDefinition.FACET_ENUMERATION)) { - formControl = - createControlForEnumerationType(xForm, - simpleType, - caption, - bindElement); - } - /*if (enumerationFacets.hasMoreElements()) { - formControl = createControlForEnumerationType(xForm, (SimpleType)controlType, caption, - bindElement); - } */ + if (simpleType.isDefinedFacet(XSSimpleTypeDefinition.FACET_ENUMERATION)) + formControl = createControlForEnumerationType(xForm, + simpleType, + caption, + bindElement); } - } else if ( - controlType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE - && controlType.getName().equals("anyType")) { + } + else if (controlType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE && + controlType.getName().equals("anyType")) + { formControl = createControlForAnyType(xForm, caption, controlType); } @@ -2752,21 +2730,9 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { (XSSimpleTypeDefinition)controlType); startFormControl(formControl, controlType); - formControl.setAttributeNS(XFORMS_NS, getXFormsNSPrefix() + "bind", bindId); - - //put the label before - // no -> put in the "createControlFor..." methods - - /*Element captionElement=xForm.createElementNS(XFORMS_NS,getXFormsNSPrefix() + "label"); - this.setXFormsId(captionElement); - captionElement.appendChild(xForm.createTextNode(caption)); - if(formControl.hasChildNodes()) - { - Node first=formControl.getFirstChild(); - captionElement = (Element) formControl.insertBefore(captionElement, first); - } - else - captionElement = (Element) formControl.appendChild(captionElement); */ + formControl.setAttributeNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "bind", + bindId); // TODO: Enhance alert statement based on facet restrictions. // TODO: Enhance to support minOccurs > 1 and maxOccurs > 1. @@ -2774,9 +2740,9 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { // // e.g. Please provide a valid value for 'Address'. 'Address' is a mandatory decimal field. // - Element alertElement = - (Element) formControl.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "alert")); + Element alertElement = (Element) + formControl.appendChild(xForm.createElementNS(XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "alert")); this.setXFormsId(alertElement); StringBuffer alert = @@ -2798,9 +2764,9 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { * @param controlType the type from which we want the name * @return the complete type name (with namespace prefix) of the type in the XForms doc */ - protected String getXFormsTypeName(Element context, XSTypeDefinition controlType) { + protected String getXFormsTypeName(Element context, XSTypeDefinition controlType) + { String result = null; - String typeName = controlType.getName(); String typeNS = controlType.getNamespace(); @@ -2850,35 +2816,31 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { String formName, String stylesheet) throws ParserConfigurationException { - Document xForm = documentBuilder.newDocument(); + final Document xForm = documentBuilder.newDocument(); - Element envelopeElement = _wrapper.createEnvelope(xForm); + final Element envelopeElement = _wrapper.createEnvelope(xForm); + + final Map namespaces = new HashMap(); + namespaces.put(SchemaFormBuilder.CHIBA_NS_PREFIX, SchemaFormBuilder.CHIBA_NS); + namespaces.put(SchemaFormBuilder.XFORMS_NS_PREFIX, SchemaFormBuilder.XFORMS_NS); + namespaces.put(SchemaFormBuilder.XLINK_NS_PREFIX, SchemaFormBuilder.XLINK_NS); + namespaces.put(SchemaFormBuilder.XMLEVENTS_NS_PREFIX, SchemaFormBuilder.XMLEVENTS_NS); + namespaces.put(SchemaFormBuilder.XMLSCHEMA_INSTANCE_NS_PREFIX, + SchemaFormBuilder.XMLSCHEMA_INSTANCE_NS); + for (String nsPrefix : namespaces.keySet()) + { + envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, + "xmlns:" + nsPrefix.substring(0, nsPrefix.length() - 1), + namespaces.get(nsPrefix)); + } - // set required namespace attributes - envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, - "xmlns:" + getChibaNSPrefix().substring(0, getChibaNSPrefix().length() - 1), - CHIBA_NS); - envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, - "xmlns:" + getXFormsNSPrefix().substring(0, getXFormsNSPrefix().length() - 1), - XFORMS_NS); - envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, - "xmlns:" + getXLinkNSPrefix().substring(0, getXLinkNSPrefix().length() - 1), - XLINK_NS); - //XMLEvent - envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, - "xmlns:" + xmleventsNSPrefix.substring(0, xmleventsNSPrefix.length() - 1), - XMLEVENTS_NS); - //XML Schema Instance - envelopeElement.setAttributeNS(XMLNS_NAMESPACE_URI, - "xmlns:" + xmlSchemaInstancePrefix.substring(0, xmlSchemaInstancePrefix.length() - 1), - XMLSCHEMA_INSTANCE_NAMESPACE_URI); //base if (_base != null && _base.length() != 0) envelopeElement.setAttributeNS(XML_NAMESPACE_URI, "xml:base", _base); //model element Element modelElement = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "model"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "model"); this.setXFormsId(modelElement); Element modelWrapper = _wrapper.createModelWrapper(modelElement); envelopeElement.appendChild(modelWrapper); @@ -2898,7 +2860,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { // add a group node and recurse // Element groupElement = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "group"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "group"); groupElement = startFormGroup(groupElement, owner); if (groupElement == null) @@ -2915,7 +2877,7 @@ public abstract class AbstractSchemaFormBuilder implements SchemaFormBuilder { Element captionElement = (Element) groupElement.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); this.setXFormsId(captionElement); captionElement.appendChild(xForm.createTextNode(createCaption(owner))); } diff --git a/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseSchemaFormBuilder.java b/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseSchemaFormBuilder.java index 3a7ac8f6ee..209728ee8e 100644 --- a/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseSchemaFormBuilder.java +++ b/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseSchemaFormBuilder.java @@ -167,15 +167,17 @@ public class BaseSchemaFormBuilder public Element createControlForAnyType(Document xForm, String caption, XSTypeDefinition controlType) { - Element control = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "textarea"); + Element control = xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "textarea"); this.setXFormsId(control); - control.setAttributeNS(CHIBA_NS, getChibaNSPrefix() + "height", "3"); + control.setAttributeNS(SchemaFormBuilder.CHIBA_NS, + SchemaFormBuilder.CHIBA_NS_PREFIX + "height", + "3"); //label Element captionElement = (Element) - control.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + control.appendChild(xForm.createElementNS(SchemaFormBuilder.XFORMS_NS, + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); this.setXFormsId(captionElement); captionElement.appendChild(xForm.createTextNode(caption)); @@ -199,24 +201,24 @@ public class BaseSchemaFormBuilder if ("boolean".equals(controlType.getName())) { control = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "select1"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "select1"); control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", "full"); this.setXFormsId(control); Element item_true = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); this.setXFormsId(item_true); Element label_true = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); this.setXFormsId(label_true); Text label_true_text = xForm.createTextNode("true"); label_true.appendChild(label_true_text); item_true.appendChild(label_true); Element value_true = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); this.setXFormsId(value_true); Text value_true_text = xForm.createTextNode("true"); value_true.appendChild(value_true_text); @@ -224,17 +226,17 @@ public class BaseSchemaFormBuilder control.appendChild(item_true); Element item_false = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); this.setXFormsId(item_false); Element label_false = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); this.setXFormsId(label_false); Text label_false_text = xForm.createTextNode("false"); label_false.appendChild(label_false_text); item_false.appendChild(label_false); Element value_false = - xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value"); + xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); this.setXFormsId(value_false); Text value_false_text = xForm.createTextNode("false"); value_false.appendChild(value_false_text); @@ -243,14 +245,14 @@ public class BaseSchemaFormBuilder } else { - control = xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "input"); + control = xForm.createElementNS(XFORMS_NS, SchemaFormBuilder.XFORMS_NS_PREFIX + "input"); this.setXFormsId(control); } //label Element captionElement = (Element) control.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); this.setXFormsId(captionElement); captionElement.appendChild(xForm.createTextNode(caption)); @@ -283,18 +285,18 @@ public class BaseSchemaFormBuilder Vector enumValues = new Vector(); Element control = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "select1"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "select1"); this.setXFormsId(control); //label Element captionElement1 = (Element) control.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); this.setXFormsId(captionElement1); captionElement1.appendChild(xForm.createTextNode(caption)); Element choices = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "choices"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "choices"); this.setXFormsId(choices); for (int i = 0; i < nbFacets; i++) { @@ -304,11 +306,11 @@ public class BaseSchemaFormBuilder if (nbFacets < Long.parseLong(getProperty(SELECTONE_LONG_LIST_SIZE_PROP))) { control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", getProperty(SELECTONE_UI_CONTROL_SHORT_PROP)); } else { control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", getProperty(SELECTONE_UI_CONTROL_LONG_PROP)); // add the "Please select..." instruction item for the combobox @@ -318,20 +320,20 @@ public class BaseSchemaFormBuilder { String pleaseSelect = "[Select1 " + caption + "]"; Element item = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "item"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "item"); this.setXFormsId(item); choices.appendChild(item); Element captionElement = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label"); this.setXFormsId(captionElement); item.appendChild(captionElement); captionElement.appendChild(xForm.createTextNode(pleaseSelect)); Element value = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "value"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "value"); this.setXFormsId(value); item.appendChild(value); value.appendChild(xForm.createTextNode(pleaseSelect)); @@ -344,13 +346,13 @@ public class BaseSchemaFormBuilder //check if there was a constraint String constraint = bindElement.getAttributeNS(XFORMS_NS, "constraint"); - constraint = ((constraint != null && constraint.length() != 0) - ? constraint + " and " + isValidExpr - : isValidExpr); + constraint = (constraint != null && constraint.length() != 0 + ? constraint + " and " + isValidExpr + : isValidExpr); bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "constraint", - constraint); + SchemaFormBuilder.XFORMS_NS_PREFIX + "constraint", + constraint); } } @@ -381,13 +383,13 @@ public class BaseSchemaFormBuilder if (nbFacets <= 0) return null; Element control = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "select"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "select"); this.setXFormsId(control); //label Element captionElement = (Element) control.appendChild(xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "label")); + SchemaFormBuilder.XFORMS_NS_PREFIX + "label")); this.setXFormsId(captionElement); captionElement.appendChild(xForm.createTextNode(caption)); @@ -402,24 +404,26 @@ public class BaseSchemaFormBuilder // // For now, use checkbox if there are < DEFAULT_LONG_LIST_MAX_SIZE items, otherwise use long control // - if (enumValues.size() - < Long.parseLong(getProperty(SELECTMANY_LONG_LIST_SIZE_PROP))) { + if (enumValues.size() < Long.parseLong(getProperty(SELECTMANY_LONG_LIST_SIZE_PROP))) + { control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", - getProperty(SELECTMANY_UI_CONTROL_SHORT_PROP)); - } else { + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", + getProperty(SELECTMANY_UI_CONTROL_SHORT_PROP)); + } + else + { control.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "appearance", - getProperty(SELECTMANY_UI_CONTROL_LONG_PROP)); + SchemaFormBuilder.XFORMS_NS_PREFIX + "appearance", + getProperty(SELECTMANY_UI_CONTROL_LONG_PROP)); } Element choices = xForm.createElementNS(XFORMS_NS, - getXFormsNSPrefix() + "choices"); + SchemaFormBuilder.XFORMS_NS_PREFIX + "choices"); this.setXFormsId(choices); control.appendChild(choices); - addChoicesForSelectControl(xForm, choices, enumValues); + this.addChoicesForSelectControl(xForm, choices, enumValues); return control; } @@ -431,7 +435,8 @@ public class BaseSchemaFormBuilder * @param node __UNDOCUMENTED__ * @return __UNDOCUMENTED__ */ - public Element createHint(Document xForm, XSObject node) { + public Element createHint(Document xForm, XSObject node) + { XSAnnotation annotation = null; if (node instanceof XSElementDeclaration) annotation = ((XSElementDeclaration) node).getAnnotation(); @@ -441,10 +446,9 @@ public class BaseSchemaFormBuilder annotation = ((XSAttributeUse) node).getAttrDeclaration().getAnnotation(); - if (annotation != null) - return addHintFromDocumentation(xForm, annotation); - else - return null; + return (annotation != null + ? addHintFromDocumentation(xForm, annotation) + : null); } /** @@ -452,8 +456,8 @@ public class BaseSchemaFormBuilder * * @param bindElement __UNDOCUMENTED__ */ - public void endBindElement(Element bindElement) { - return; + public void endBindElement(Element bindElement) + { } /** @@ -506,12 +510,12 @@ public class BaseSchemaFormBuilder String typeName = this.getXFormsTypeName(enveloppe, controlType); if (typeName != null && typeName.length() != 0) bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "type", + SchemaFormBuilder.XFORMS_NS_PREFIX + "type", typeName); } bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "required", + SchemaFormBuilder.XFORMS_NS_PREFIX + "required", o.minimum == 0 ? "false()" : "true()"); @@ -528,19 +532,14 @@ public class BaseSchemaFormBuilder //if 1 or unbounded -> no constraint maxConstraint = "count(.) <= " + o.maximum; - String constraint = null; - - if ((minConstraint != null) && (maxConstraint != null)) { - constraint = minConstraint + " and " + maxConstraint; - } else if (minConstraint != null) { - constraint = minConstraint; - } else { - constraint = maxConstraint; - } - + final String constraint = (minConstraint != null && maxConstraint != null + ? minConstraint + " and " + maxConstraint + : (minConstraint != null + ? minConstraint + : maxConstraint)); if (constraint != null && constraint.length() != 0) bindElement.setAttributeNS(XFORMS_NS, - getXFormsNSPrefix() + "constraint", + SchemaFormBuilder.XFORMS_NS_PREFIX + "constraint", constraint); return bindElement; } @@ -553,7 +552,8 @@ public class BaseSchemaFormBuilder * @return __UNDOCUMENTED__ */ public Element startFormControl(Element controlElement, - XSTypeDefinition controlType) { + XSTypeDefinition controlType) + { return controlElement; } @@ -565,7 +565,8 @@ public class BaseSchemaFormBuilder * @return __UNDOCUMENTED__ */ public Element startFormGroup(Element groupElement, - XSElementDeclaration schemaElement) { + XSElementDeclaration schemaElement) + { //groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "box-align",getProperty(GROUP_BOX_ALIGN_PROP)); //groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "box-orient",getProperty(GROUP_BOX_ORIENT_PROP)); //groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "caption-width",getProperty(GROUP_CAPTION_WIDTH_PROP)); diff --git a/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseWrapperElementsBuilder.java b/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseWrapperElementsBuilder.java deleted file mode 100644 index ba4333b9d9..0000000000 --- a/source/java/org/alfresco/web/templating/xforms/schemabuilder/BaseWrapperElementsBuilder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * 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.alfresco.web.templating.xforms.schemabuilder; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Basic implementation of WrapperElementsBuilder, with no additional design - * - * @author - Sophie Ramel - */ -public class BaseWrapperElementsBuilder implements WrapperElementsBuilder { - /** - * Creates a new instance of BaseWrapperElementsBuilder - */ - public BaseWrapperElementsBuilder() { - } - - /** - * create the wrapper element of the different controls - * - * @param controlElement the control element (input, select, repeat, group, ...) - * @return the wrapper element, already containing the control element - */ - public Element createControlsWrapper(Element controlElement) { - return controlElement; - } - - /** - * creates the global enveloppe of the resulting document, and puts it in the document - * - * @return the enveloppe - */ - public Element createEnvelope(Document xForm) { - Element envelopeElement = xForm.createElement("envelope"); - - //Element envelopeElement = xForm.createElementNS(CHIBA_NS, this.getChibaNSPrefix()+"envelope"); - xForm.appendChild(envelopeElement); - - return envelopeElement; - } - - /** - * create the wrapper element of the form - * - * @param enveloppeElement the form element (chiba:form or other) - * @return the wrapper element - */ - - public Element createFormWrapper(Element enveloppeElement) { - //add a "body" element without NS - Document doc = enveloppeElement.getOwnerDocument(); - Element body = doc.createElement("body"); - //body.appendChild(formElement); - enveloppeElement.appendChild(body); - return body; - } - - /** - * create the element that will contain the content of the group (or repeat) element - * - * @param groupElement the group or repeat element - * @return the wrapper element, already containing the content of the group element - */ - public Element createGroupContentWrapper(Element groupElement) { - return groupElement; - } - - /** - * create the wrapper element of the xforms:model element - * - * @param modelElement the xforms:model element - * @return the wrapper element, already containing the model - */ - public Element createModelWrapper(Element modelElement) { - return modelElement; - } -} diff --git a/source/java/org/alfresco/web/templating/xforms/schemabuilder/SchemaFormBuilder.java b/source/java/org/alfresco/web/templating/xforms/schemabuilder/SchemaFormBuilder.java index 825a0f9075..97a61aaf83 100644 --- a/source/java/org/alfresco/web/templating/xforms/schemabuilder/SchemaFormBuilder.java +++ b/source/java/org/alfresco/web/templating/xforms/schemabuilder/SchemaFormBuilder.java @@ -92,9 +92,14 @@ public interface SchemaFormBuilder /** * XMLSchema Instance Namespace declaration */ - public static final String XMLSCHEMA_INSTANCE_NAMESPACE_URI = + public static final String XMLSCHEMA_INSTANCE_NS = "http://www.w3.org/2001/XMLSchema-instance"; + /** + * XMLSchema instance prefix * + */ + public static final String XMLSCHEMA_INSTANCE_NS_PREFIX = "xsi:"; + /** * XMLNS Namespace declaration. */ @@ -110,7 +115,13 @@ public interface SchemaFormBuilder /** * XForms namespace declaration. */ - public static final String XFORMS_NS = "http://www.w3.org/2002/xforms"; + public static final String XFORMS_NS = + "http://www.w3.org/2002/xforms"; + + /** + * XForms prefix + */ + public static final String XFORMS_NS_PREFIX = "xforms:"; /** * Chiba namespace declaration. @@ -118,40 +129,30 @@ public interface SchemaFormBuilder public static final String CHIBA_NS = "http://chiba.sourceforge.net/xforms"; + /** + * Chiba prefix + */ + public static final String CHIBA_NS_PREFIX = "chiba:"; + /** * XLink namespace declaration. */ public static final String XLINK_NS = "http://www.w3.org/1999/xlink"; + /** + * Xlink prefix + */ + public static final String XLINK_NS_PREFIX = "xlink:"; + /** * XML Events namsepace declaration. */ public static final String XMLEVENTS_NS = "http://www.w3.org/2001/xml-events"; - /** - * Chiba prefix - */ - public static final String chibaNSPrefix = "chiba:"; - - /** - * XForms prefix - */ - public static final String xformsNSPrefix = "xforms:"; - - /** - * Xlink prefix - */ - public static final String xlinkNSPrefix = "xlink:"; - - /** - * XMLSchema instance prefix * - */ - public static final String xmlSchemaInstancePrefix = "xsi:"; - /** * XML Events prefix */ - public static final String xmleventsNSPrefix = "ev:"; + public static final String XMLEVENTS_NS_PREFIX = "ev:"; /** * Prossible values of the "@method" on the "submission" element diff --git a/source/web/images/icons/arrow_down.gif b/source/web/images/icons/arrow_down.gif new file mode 100644 index 0000000000..0c9b4f906a Binary files /dev/null and b/source/web/images/icons/arrow_down.gif differ diff --git a/source/web/images/icons/arrow_up.gif b/source/web/images/icons/arrow_up.gif new file mode 100644 index 0000000000..f26caab535 Binary files /dev/null and b/source/web/images/icons/arrow_up.gif differ diff --git a/source/web/images/icons/minus.gif b/source/web/images/icons/minus.gif new file mode 100644 index 0000000000..87776787f0 Binary files /dev/null and b/source/web/images/icons/minus.gif differ diff --git a/source/web/images/icons/plus.gif b/source/web/images/icons/plus.gif new file mode 100644 index 0000000000..91c38ac0ca Binary files /dev/null and b/source/web/images/icons/plus.gif differ diff --git a/source/web/jsp/dashboards/dashlets/getting-started.jsp b/source/web/jsp/dashboards/dashlets/getting-started.jsp index c8b4eee5fc..e78315d840 100644 --- a/source/web/jsp/dashboards/dashlets/getting-started.jsp +++ b/source/web/jsp/dashboards/dashlets/getting-started.jsp @@ -24,7 +24,7 @@ <% PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellow", "#ffffcc"); %> - + diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js index 86c5657d46..34a76d7b45 100644 --- a/source/web/scripts/ajax/xforms.js +++ b/source/web/scripts/ajax/xforms.js @@ -23,6 +23,14 @@ tinyMCE.init({ theme_advanced_buttons2_add : "separator,forecolor,backcolor" }); +var control_images = [ "plus", "minus", "arrow_up", "arrow_down" ]; +for (var i in control_images) +{ + var s = control_images[i]; + control_images[i] = new Image(); + control_images[i].src = s; +} + dojo.declare("alfresco.xforms.Widget", null, { @@ -30,13 +38,26 @@ dojo.declare("alfresco.xforms.Widget", { this.xform = xform; this.node = node; + this.node.widget = this; this.id = this.node.getAttribute("id"); }, parent: null, + domContainer: null, _getBinding: function() { return this.xform.getBinding(this.node); }, + getDepth: function() + { + var result = 1; + var p = this.parent; + while (p) + { + result++; + p = p.parent; + } + return result; + }, isRequired: function() { var binding = this._getBinding(); @@ -114,16 +135,18 @@ dojo.declare("alfresco.xforms.NumericStepper", value: initial_value }, nodeRef); - var handler = function(event) - { - dojo.debug("value changed " + w.widgetId + - " value " + w.getValue() + - " t " + event.target + - " w " + w + " this " + this); - setXFormsValue(w.widgetId, w.getValue()); - } - dojo.event.connect(w, "adjustValue", handler); - dojo.event.connect(w, "onkeyup", handler); + w.widget = this; + this.widget = w; + dojo.event.connect(w, "adjustValue", this, this._widget_changeHandler); + dojo.event.connect(w, "onkeyup", this, this._widget_changeHandler); + }, + getValue: function() + { + return this.widget.getValue(); + }, + _widget_changeHandler: function(event) + { + this.xform.setXFormsValue(this.id, this.getValue()); } }); @@ -164,13 +187,14 @@ dojo.declare("alfresco.xforms.DatePicker", dateTextBox.picker.hide(); dojo.event.connect(dateTextBox.picker, "onSetDate", + this, function(event) { dateTextBox.picker.hide(); dateTextBox.show(); dateTextBox.setValue(dojo.widget.DatePicker.util.toRfcDate(dateTextBox.picker.date)); - setXFormsValue(dateTextBox.widgetId, - dateTextBox.getValue()); + this.xform.setXFormsValue(dateTextBox.widgetId, + dateTextBox.getValue()); }); } }); @@ -195,16 +219,17 @@ dojo.declare("alfresco.xforms.TextField", value: initial_value }, nodeRef); - dojo.event.connect(w, - "onkeyup", - function(event) - { - dojo.debug("value changed " + w.widgetId + - " value " + w.getValue() + - " t " + event.target + - " w " + w + " this " + this); - setXFormsValue(w.widgetId, w.getValue()); - }); + w.widget = this; + this.widget = w; + dojo.event.connect(w, "onkeyup", this, this._widget_keyUpHandler); + }, + getValue: function() + { + return this.widget.getValue(); + }, + _widget_keyUpHandler: function(event) + { + this.xform.setXFormsValue(this.id, this.getValue()); } }); @@ -277,8 +302,8 @@ dojo.declare("alfresco.xforms.Select1", radio.setAttribute("checked", "true"); radio.onclick = function(event) { - setXFormsValue(this.getAttribute("id"), - this.value); + this.xform.setXFormsValue(this.getAttribute("id"), + this.value); } attach_point.appendChild(radio); attach_point.appendChild(document.createTextNode(values[i].label)); @@ -300,8 +325,8 @@ dojo.declare("alfresco.xforms.Select1", } combobox.onchange = function(event) { - setXFormsValue(this.getAttribute("id"), - this.options[this.selectedIndex].value); + this.xform.setXFormsValue(this.getAttribute("id"), + this.options[this.selectedIndex].value); } } } @@ -329,7 +354,7 @@ dojo.declare("alfresco.xforms.CheckBox", "onClick", function(event) { - setXFormsValue(w.widgetId, w.checked); + this.xform.setXFormsValue(w.widgetId, w.checked); }); } }); @@ -340,45 +365,289 @@ dojo.declare("alfresco.xforms.Group", initializer: function(xform, node) { this.inherited("initializer", [ xform, node ]); + this.children = []; }, - children: [], + children: null, + getChildAt: function(index) + { + return index < this.children.length ? this.children[index] : null; + }, + getChildIndex: function(child) + { + for (var i = 0; i < this.children.length; i++) + { + dojo.debug(this.id + "[" + i + "]: " + + " is " + this.children[i].id + " the same as " + child.id + "?"); + if (this.children[i] == child) + return i; + } + return -1; + }, domNode: null, addChild: function(child) { - this.children.push(child); + return this.insertChildAt(child, this.children.length); + }, + insertChildAt: function(child, position) + { + dojo.debug(this.id + ".insertChildAt(" + child.id + ", " + position + ")"); child.parent = this; + var d = document.createElement("div"); - d.setAttribute("style", "border: 2px solid green; width: 100%;"); - this.domNode.appendChild(d); - if (child.isRequired() && child.node.nodeName != "xforms:repeat") + child.domContainer = d; + d.setAttribute("style", "position: relative; border: 0px solid green; margin-top: 2px; margin-bottom: 2px;"); + if (this.parent && this.parent.domNode) + d.style.top = this.parent.domNode.style.bottom; + + if (position == this.children.length) + { + this.domNode.appendChild(d); + this.children.push(child); + } + else + { + this.domNode.insertBefore(d, this.getChildAt(position).domContainer); + this.children.splice(position, 0, child); + } + + if (child.isRequired() && !(child instanceof alfresco.xforms.Group)) { var requiredImage = document.createElement("img"); requiredImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/required_field.gif"); - requiredImage.setAttribute("style", "margin:5px"); - requiredImage.setAttribute("alt", "node Name " + child.node.nodeName); + requiredImage.setAttribute("style", "margin:5px;"); d.appendChild(requiredImage); + requiredImage.style.position = "relative"; + requiredImage.style.top = "0px"; + requiredImage.style.left = "0px"; + requiredImage.style.lineHeight = d.style.height; } var label = child._getLabelNode(); - if (label) - d.appendChild(document.createTextNode(dojo.dom.textContent(label))); - var s = document.createElement("span"); - d.appendChild(s); - child.render(s); + if (label && !(child instanceof alfresco.xforms.Group)) + { + var labelDiv = document.createElement("div"); + labelDiv.appendChild(document.createTextNode(dojo.dom.textContent(label))); + d.appendChild(labelDiv); + labelDiv.style.position = "relative"; + labelDiv.style.top = "-" + labelDiv.offsetTop + "px"; + labelDiv.style.left = "5%"; + } + var contentDiv = document.createElement("div"); + d.appendChild(contentDiv); + child.render(contentDiv); + contentDiv.style.position = "relative"; + contentDiv.style.top = "-" + contentDiv.offsetTop + "px"; + contentDiv.style.left = (child instanceof alfresco.xforms.Group + ? "0px" + : "40%"); + d.style.borderColor = "pink"; + d.style.borderWidth = "0px"; + if (!(child instanceof alfresco.xforms.Group)) + d.style.height = contentDiv.offsetHeight; + return d; }, + isIndented: function() + { + return false && this.parent != null; + }, render: function(attach_point) { this.domNode = document.createElement("div"); - this.domNode.setAttribute("style", "width:100%; border: 0px solid blue;"); - if (parent) + this.domNode.setAttribute("id", this.id + "-domNode"); + this.domNode.widget = this; + this.domNode.setAttribute("style", "border: 0px solid blue;"); + if (this.isIndented()) this.domNode.style.marginLeft = "10px"; attach_point.appendChild(this.domNode); return this.domNode; } }); -dojo.declare("alfresco.xforms.Submit", +dojo.declare("alfresco.xforms.Repeat", + alfresco.xforms.Group, + { + initializer: function(xform, node) + { + this.inherited("initializer", [ xform, node ]); + }, + selectedIndex: null, + insertChildAt: function(child, position) + { + var result = this.inherited("insertChildAt", [ child, position ]); + result.style.borderColor = "green"; + result.style.borderWidth = "0px"; + child.repeat = this; + + dojo.event.browser.addListener(result, "onclick", function(event) + { + child.repeat.setFocusedChild(child); + }); + + var controls = document.createElement("div"); + result.appendChild(controls); + controls.style.position = "absolute"; + controls.style.left = "80%"; + controls.style.bottom = "0px"; + + var images = [ + { src: "plus", action: this._insertRepeatItem_handler }, + { src: "arrow_up", action: this._moveRepeatItemUp_handler }, + { src: "arrow_down", action: null }, + { src: "minus", action: null } + ]; + for (var i in images) + { + var img = document.createElement("img"); + img.setAttribute("src", + WEBAPP_CONTEXT + "/images/icons/" + images[i].src + ".gif"); + img.style.width = "16px"; + img.style.height = "16px"; + img.style.marginRight = "4px"; + img.repeatItem = child; + img.repeat = this; + controls.appendChild(img); + dojo.event.browser.addListener(img, "onclick", images[i].action); + } + + return result; + }, + _insertRepeatItem_handler: function(event) + { + alert("insert r=" + event.target.repeat.id + + " item " + event.target.repeatItem.id); + }, + _moveRepeatItemUp_handler: function(event) + { + alert("moveUp " + event); + }, + setFocusedChild: function(child) + { + if (!child) + this.xform.setRepeatIndex(this.id, 0); + else + { + var index = this.getChildIndex(child); + if (index < 0) + alert("unable to find child " + child.id + " in " + this.id); + + // chiba thinks indexes are initialized to 1 so just + // highlight the thing + if (this.selectedIndex == null && index == 0) + this.handleIndexChanged(0); + // xforms repeat indexes are 1-based + this.xform.setRepeatIndex(this.id, index + 1); + + } + }, + isIndented: function() + { + return false; + }, + render: function(attach_point) + { + this.domNode = this.inherited("render", [ attach_point ]); + this.domNode.style.borderColor = "black"; + this.domNode.style.borderWidth = "1px"; + + var d = document.createElement("div"); + d.repeat = this; + this.domNode.appendChild(d); + d.setAttribute("style", "position: relative; line-height: 16px; background-color: #cddbe8; font-weight: bold;"); + dojo.event.browser.addListener(d, "onclick", function(event) + { + event.currentTarget.repeat.setFocusedChild(null); + }); + + var labelElement = document.createElement("div"); + d.appendChild(labelElement); + labelElement.appendChild(document.createTextNode(this.parent.getLabel())); + labelElement.setAttribute("style", "position: relative; left: 5%; top: 0px;"); + + var addElement = document.createElement("img"); + d.appendChild(addElement); + addElement.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/plus.gif"); + addElement.style.width = "16px"; + addElement.style.height = "16px"; + addElement.style.position = "absolute"; + addElement.style.top = "0px"; + addElement.style.left = "80%"; + + dojo.event.browser.addListener(addElement, "onclick", function(event) + { + var repeat = event.currentTarget.parentNode.repeat; + repeat.xform.fireAction("trigger_0"); + }); + + return this.domNode; + }, + handleIndexChanged: function(index) + { + dojo.debug(this.id + ".handleIndexChanged(" + index + ")"); + if (this.selectedIndex != null && this.selectedIndex >= 0) + { + var child = this.getChildAt(this.selectedIndex); + child.domContainer.style.backgroundColor = "white"; + } + + if (index >= 0) + { + var child = this.getChildAt(index); + child.domContainer.style.backgroundColor = "orange"; + } + this.selectedIndex = index; + }, + handlePrototypeCloned: function(prototypeId) + { + dojo.debug(this.id + ".handlePrototypeCloned("+ prototypeId +")"); + var chibaData = this.node.getElementsByTagName("data"); + dojo.debug("repeat node == " +dojo.dom.innerXML(this.node)); + dojo.debug(chibaData + " l = " + chibaData.length); + chibaData = chibaData[chibaData.length - 1]; + dojo.debug("chiba:data == " + dojo.dom.innerXML(chibaData)); + var prototypeToClone = dojo.dom.firstElement(chibaData); + if (prototypeToClone.getAttribute("id") != prototypeId) + throw new Error("unable to locate " + prototypeId + + " in " + this.id); + return prototypeToClone.cloneNode(true); + }, + handleItemInserted: function(clonedPrototype, position) + { + dojo.debug(this.id + ".handleItemInserted(" + clonedPrototype.nodeName + + ", " + position + ")"); + var w = create_widget(this.xform, clonedPrototype); + this.insertChildAt(w, position); + load_body(this.xform, w.node, w); + } + }); + +dojo.declare("alfresco.xforms.Trigger", alfresco.xforms.Widget, { + initializer: function(xform, node) + { + this.inherited("initializer", [ xform, node ]); + }, + + render: function(attach_point) + { + var nodeRef = document.createElement("div"); + attach_point.appendChild(nodeRef); + var w = dojo.widget.createWidget("Button", + { + widgetId: this.id, + caption: this.getLabel() + " " + this.id + }, + nodeRef); + w.onClick = function() + { + fireAction(w.widgetId); + }; + this.domContainer.style.display = "none"; + } + }); + +dojo.declare("alfresco.xforms.Submit", + alfresco.xforms.Trigger, + { initializer: function(xform, node) { this.inherited("initializer", [ xform, node ]); @@ -403,36 +672,13 @@ dojo.declare("alfresco.xforms.Submit", } }); -dojo.declare("alfresco.xforms.Trigger", - alfresco.xforms.Widget, - { - initializer: function(xform, node) - { - this.inherited("initializer", [ xform, node ]); - }, - render: function(attach_point) - { - var nodeRef = document.createElement("div"); - attach_point.appendChild(nodeRef); - var w = dojo.widget.createWidget("Button", - { - widgetId: this.id, - caption: this.getLabel() + " " + this.id - }, - nodeRef); - w.onClick = function() - { - fireAction(w.widgetId); - }; - } - }); - dojo.declare("alfresco.xforms.XForm", null, { - initializer: function(node) + initializer: function(document) { - this.node = node; + this.document = document; + this.node = document.documentElement; this._bindings = this._loadBindings(this.getModel()); }, getModel: function() @@ -461,7 +707,7 @@ dojo.declare("alfresco.xforms.XForm", { return this._bindings; }, - _loadBindings: function(bind, parent, result) + _loadBindings: function(bind, parent, result) { result = result || []; dojo.debug("loading bindings for " + bind.nodeName); @@ -482,6 +728,164 @@ dojo.declare("alfresco.xforms.XForm", } } return result; + }, + setRepeatIndex: function(id, index) + { + dojo.debug("setting repeat index " + index + " on " + id); + var req = { + xform: this, + url: WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.setRepeatIndex", + content: { id: id, index: index }, + mimetype: "text/xml", + load: function(type, data, evt) + { + this.xform._handleEventLog(data.documentElement); + }, + error: function(type, e) + { + alert("error!! " + type + " e = " + e.message); + } + }; + dojo.io.bind(req); + }, + fireAction: function(id) + { + var req = { + xform: this, + url: WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.fireAction", + content: { id: id }, + mimetype: "text/xml", + load: function(type, data, evt) + { + dojo.debug("fireAction." + type); + this.xform._handleEventLog(data.documentElement); + if (document.submitTrigger) + { + document.submitTrigger.done = true; + document.submitTrigger.currentButton.click(); + document.submitTrigger.currentButton = null; + } + }, + error: function(type, e) + { + alert("error!! " + type + " e = " + e.message); + } + }; + dojo.io.bind(req); + }, + setXFormsValue: function(id, value) + { + dojo.debug("setting value " + id + " = " + value); + var req = { + xform: this, + url: WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.setXFormsValue", + content: { id: id, value: value }, + mimetype: "text/xml", + load: function(type, data, evt) + { + this.xform._handleEventLog(data.documentElement); + }, + error: function(type, e) + { + alert("error!! " + type + " e = " + e.message); + } + }; + dojo.io.bind(req); + }, + _handleEventLog: function(events) + { + var prototypeClones = []; + for (var i = 0; i < events.childNodes.length; i++) + { + if (dojo.dom.isNode(events.childNodes[i])) + { + var targetId = events.childNodes[i].getAttribute("targetId"); + var targetName = events.childNodes[i].getAttribute("targetName"); + dojo.debug("parsing " + events.childNodes[i].nodeName + + "(" + targetId + ", " + targetName + ")"); + switch (events.childNodes[i].nodeName) + { + case "chiba-index-changed": + { + var index = events.childNodes[i].getElementsByTagName("index")[0]; + index = Number(dojo.dom.textContent(index)) - 1; + + var targetDomNode = document.getElementById(targetId + "-domNode"); + if (!targetDomNode) + throw new Error("unable to find node " + targetId + "-domNode"); + var target = targetDomNode.widget; + + target.handleIndexChanged(index); + break; + } + case "chiba-prototype-cloned": + { + var prototypeId = events.childNodes[i].getElementsByTagName("prototypeId")[0]; + prototypeId = dojo.dom.textContent(prototypeId); + + var targetDomNode = document.getElementById(targetId + "-domNode"); + if (!targetDomNode) + throw new Error("unable to find node " + targetId + "-domNode"); + var target = targetDomNode.widget; + + var clone = target.handlePrototypeCloned(prototypeId); + prototypeClones.push(clone); + break; + } + case "chiba-id-generated": + { + var originalId = events.childNodes[i].getElementsByTagName("originalId")[0]; + originalId = dojo.dom.textContent(originalId); + + dojo.debug("handleIdGenerated(" + targetId + ", " + originalId + ")"); + function applyId(node, oldId, newId) + { + dojo.debug("looking for " + oldId + + " in " + node.nodeName + + "(" + node.getAttribute("id") + ")"); + if (node.getAttribute("id") == oldId) + { + dojo.debug("applying id " + newId + + " to " + node.nodeName + "(" + oldId + ")"); + node.setAttribute("id", newId); + return true; + } + for (var i = 0; i < node.childNodes.length; i++) + { + if (dojo.dom.isNode(node.childNodes[i]) && + applyId(node.childNodes[i], oldId, newId)) + return true; + } + return false; + } + + var clone = prototypeClones[prototypeClones.length - 1]; + if (!applyId(clone, originalId, targetId)) + throw new Error("unable to find " + originalId + + " in clone " + dojo.dom.innerXML(clone)); + break; + } + case "chiba-item-inserted": + { + var position = events.childNodes[i].getElementsByTagName("position")[0]; + position = Number(dojo.dom.textContent(position)) - 1; + + var targetDomNode = document.getElementById(targetId + "-domNode"); + if (!targetDomNode) + throw new Error("unable to find node " + targetId + "-domNode"); + var target = targetDomNode.widget; + + var clone = prototypeClones.pop(); + target.handleItemInserted(clone, position); + break; + } + default: + { + dojo.debug("unhandled event " + events.childNodes[i].nodeName); + } + } + } + } } }); @@ -493,7 +897,7 @@ function xforms_init() mimetype: "text/xml", load: function(type, data, evt) { - var xform = new alfresco.xforms.XForm(data.documentElement); + var xform = new alfresco.xforms.XForm(data); var bindings = xform.getBindings(); for (var i in bindings) { @@ -515,110 +919,66 @@ function xforms_init() dojo.io.bind(req); } -function load_body(xform, currentNode, parentWidget) +function create_widget(xform, node) { - dojo.lang.forEach(currentNode.childNodes, function(o) - { - dojo.debug("loading " + o + " NN " + o.nodeName + " into " + parentWidget); - switch (o.nodeName.toLowerCase()) + switch (node.nodeName.toLowerCase()) { case "xforms:group": - var w = new alfresco.xforms.Group(xform, o); - dojo.debug("adding " + w + " to " + parentWidget); - parentWidget.addChild(w); - load_body(xform, o, w); - break; + return new alfresco.xforms.Group(xform, node); case "xforms:repeat": - var w = new alfresco.xforms.Group(xform, o); - parentWidget.addChild(w); - load_body(xform, o, w); - break; + return new alfresco.xforms.Repeat(xform, node); case "xforms:textarea": - var w = new alfresco.xforms.TextArea(xform, o); - parentWidget.addChild(w); - break; + return new alfresco.xforms.TextArea(xform, node); case "xforms:input": - var type = xform.getType(o); + var type = xform.getType(node); switch (type) { case "date": - var w = new alfresco.xforms.DatePicker(xform, o); - break; + return new alfresco.xforms.DatePicker(xform, node); case "integer": case "positiveInteger": case "negativeInteger": case "double": - var w = new alfresco.xforms.NumericStepper(xform, o, type); - break; + return new alfresco.xforms.NumericStepper(xform, node, type); case "string": default: - var w = new alfresco.xforms.TextField(xform, o); + return new alfresco.xforms.TextField(xform, node); } - parentWidget.addChild(w); - break; case "xforms:select1": - var w = (xform.getType(o) == "boolean" - ? new alfresco.xforms.CheckBox(xform, o) - : new alfresco.xforms.Select1(xform, o)); - parentWidget.addChild(domNode); - break; + return (xform.getType(node) == "boolean" + ? new alfresco.xforms.CheckBox(xform, node) + : new alfresco.xforms.Select1(xform, node)); case "xforms:submit": - var w = new alfresco.xforms.Submit(xform, o); - parentWidget.addChild(w); - break; + return new alfresco.xforms.Submit(xform, node); case "xforms:trigger": - var w = new alfresco.xforms.Trigger(xform, o); - parentWidget.addChild(w); - break; + return new alfresco.xforms.Trigger(xform, node); case "chiba:data": - break; + case "xforms:label": + case "xforms:alert": + return null; default: - load_body(xform, o, parentWidget); - break; + throw new Error("unknown type " + node.nodeName); + } +} + +function load_body(xform, currentNode, parentWidget) +{ + dojo.lang.forEach(currentNode.childNodes, function(o) + { + if (dojo.dom.isNode(o)) + { + dojo.debug("loading " + o + " NN " + o.nodeName + " into " + parentWidget); + var w = create_widget(xform, o); + if (w != null) + { + parentWidget.addChild(w); + if (w instanceof alfresco.xforms.Group) + load_body(xform, o, w); + } } }); } -function fireAction(id) -{ - var req = { - url: WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.fireAction", - content: { id: id }, - mimetype: "text/xml", - load: function(type, data, evt) - { - if (document.submitTrigger) - { - document.submitTrigger.done = true; - document.submitTrigger.currentButton.click(); - document.submitTrigger.currentButton = null; - } - }, - error: function(type, e) - { - alert("error!! " + type + " e = " + e.message); - } - }; - dojo.io.bind(req); -} - -function setXFormsValue(id, value) -{ - var req = { - url: WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.setXFormsValue", - content: { id: id, value: value }, - mimetype: "text/xml", - load: function(type, data, evt) - { - }, - error: function(type, e) - { - alert("error!! " + type + " e = " + e.message); - } - }; - dojo.io.bind(req); -} - function addSubmitHandlerToButton(b) { var baseOnClick = b.onclick;