Java tutorial
/* Copyright (C) 2007-2011 BlueXML - www.bluexml.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.bluexml.xforms.generator.forms.modelelement; import java.util.ArrayList; import java.util.List; import javax.xml.namespace.QName; import org.apache.commons.lang.StringUtils; import com.bluexml.xforms.messages.MsgId; import org.jdom.Element; import com.bluexml.xforms.generator.forms.ModelElement; import com.bluexml.xforms.generator.forms.XFormsGenerator; /** * The Class ModelElementBindSimple. */ public class ModelElementBindSimple extends ModelElement { /** The nodeset. */ protected String nodeset; /** The linked elements. */ protected List<Element> linkedElements = new ArrayList<Element>(); /** The constraint. */ protected String constraint = null; /** The length constraint. */ private String lengthConstraint = null; /** The type. */ protected QName type; /** The required. */ protected boolean required = false; /** The read only. */ protected boolean readOnly = false; /** The visibility of the form control. */ protected boolean hidden = false; protected ModelElementBindSimple anotherMeb = null; // if true, this item's "readonly" attribute is never set to "true" private boolean isRepeaterRootBind = false; // #1241 // #1223-related: do not add a constraint for widgets even if 'required' is set to true private boolean isAnAssociation = false; // #1420: multiple inputs need a special case for the 'required' expression. This reference // is meant to be the nodeset to the item, not the value, e.g. "Company/field_41/item" private String multipleInputReference = null; /** * Instantiates a new model element bind simple. * * @param nodeset * the nodeset */ public ModelElementBindSimple(String nodeset) { this.nodeset = nodeset; // by default, not in a workflow setInWorkflowForm(false); } /** * Adds the linked element. * * @param linkedElement * the linked element */ public void addLinkedElement(Element linkedElement) { linkedElements.add(linkedElement); } /* * (non-Javadoc) * * @see org.green.xforms.generator.forms.ModelElement#getModelElement() */ @Override public Element getModelElement() { String bindId = XFormsGenerator.getId(MsgId.INT_GEN_PREFIX_BIND_FORM.getText()); Element bindElement = XFormsGenerator.createElement("bind", XFormsGenerator.NAMESPACE_XFORMS); bindElement.setAttribute("nodeset", nodeset); bindElement.setAttribute("id", bindId); if (type != null) { // ** #1280 String typeStr = type.toString(); if ((typeStr.equalsIgnoreCase(MsgId.INT_TYPE_XSD_DATE.getText()) || typeStr.equalsIgnoreCase(MsgId.INT_TYPE_XSD_DATETIME.getText()) || typeStr.equalsIgnoreCase(MsgId.INT_TYPE_XSD_TIME.getText())) && isReadOnly()) { typeStr = "string"; // there is not much use in setting the 'type' field, we do it for being consistent. type = new QName("string"); } // ** #1280 bindElement.setAttribute("type", typeStr); } if (isRequired()) { String ref = getMultipleInputReference(); if (ref != null) { // this bind is for an input with multiple values //** #1420 String reqExpr = "instance('minstance')/" + ref + "[1]/"; reqExpr = reqExpr + MsgId.INT_INSTANCE_INPUT_MULT_VALUE + " eq ''"; bindElement.setAttribute("required", reqExpr); //** #1420 } else { bindElement.setAttribute("required", "true()"); if (isAnAssociation() == false) { setConstraint("(. ne '')"); } } } else { // if (getLengthConstraint() != null) { // bindElement.setAttribute("required", "not (string-length(.) = 0 or (" // + getLengthConstraint() + "))"); // } } if (isReadOnly()) { bindElement.setAttribute("readonly", "true()"); } if (isHidden()) { bindElement.setAttribute("relevant", "false()"); } else { // ** #1340 if (isRequired()) { // TO UPDATE in case regex fields no longer allow empty strings setRelevantAttrForGhostTemplate(bindElement); } // ** #1340 } if (StringUtils.trimToNull(constraint) != null) { bindElement.setAttribute("constraint", constraint); } for (Element linkedElement : linkedElements) { linkedElement.setAttribute("bind", bindId); } return bindElement; } /** * @param bindElement */ private void setRelevantAttrForGhostTemplate(Element bindElement) { // special processing added for telling Chiba not to validate the ghost section that // we use in repeaters as templates // example of what we want to obtain: relevant="index('field_456Repeater') < // count(instance('minstance')/NewsletterTech/field_456/associationItem)" boolean first = true; int posStart = 0; String relevantStr = ""; posStart = nodeset.indexOf("[index('", posStart); while (posStart != -1) { // there is a ghost template int posEnd = nodeset.indexOf("')]", posStart + 1); if (posEnd == -1) { // TODO: output message // if (logger.isErrorEnabled()) { // logger.error("Error when parsing a nodeset for repeater name"); // } } else { String lvalue = nodeset.substring(posStart + 1, posEnd + 2); String rvalue = nodeset.substring(0, posStart); if (first) { first = false; } else { relevantStr += " and "; } relevantStr += "(" + lvalue + " < count(" + rvalue + "))"; } posStart = nodeset.indexOf("[index('", posEnd + 1); } if (StringUtils.trimToNull(relevantStr) != null) { bindElement.setAttribute("relevant", relevantStr); } } /** * Gets the nodeset. * * @return the nodeset */ public String getNodeset() { return nodeset; } /** * Sets the constraint. * * @param constraint * the new constraint */ public void setConstraint(String constraint) { if (this.constraint != null) { this.constraint = this.constraint + " and " + constraint; } else { this.constraint = constraint; } } /** * @return the constraint */ public String getConstraint() { return constraint; } /** * Sets the nodeset. * * @param nodeset * the new nodeset */ public void setNodeset(String nodeset) { this.nodeset = nodeset; } /** * @return the required */ public boolean isRequired() { return required; } /** * Sets the required. * * @param required * the new required */ public void setRequired(boolean required) { this.required = required; } /** * @return the hidden */ public boolean isHidden() { return hidden; } /** * @param hidden * the hidden to set */ public void setHidden(boolean hidden) { this.hidden = hidden; } /** * Checks if is read only. * * @return true, if is read only */ public boolean isReadOnly() { if (isRepeaterRootBind()) { return false; } return getFormGenerator().isInReadOnlyMode() || readOnly; } /** * Sets the read only. * * @param readOnly * the new read only */ public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } /** * Sets the type. * * @param type * the new type */ public void setType(QName type) { this.type = type; } /* * (non-Javadoc) * * @see org.green.xforms.generator.forms.ModelElement#hasClone(java.util.List) */ @Override public boolean hasClone(List<ModelElement> allModelElementsClean) { for (ModelElement modelElement : allModelElementsClean) { if (modelElement == this) { return true; } if (modelElement instanceof ModelElementBindSimple) { if (!(modelElement instanceof ModelElementBindHolder)) { ModelElementBindSimple modelElementBindSimple = (ModelElementBindSimple) modelElement; String nodeset1 = removeIndices(modelElementBindSimple.nodeset); String nodeset2 = removeIndices(nodeset); if (nodeset1.equals(nodeset2)) { for (Element element : linkedElements) { modelElementBindSimple.linkedElements.add(element); } return true; } } } } return false; } /** * Removes the indices. * * @param nodeset * the nodeset * * @return the string */ private String removeIndices(String nodeset) { String[] split = StringUtils.split(nodeset, "[]"); if (split.length > 1) { StringBuffer result = new StringBuffer(""); int i = 0; for (String string : split) { if (i % 2 == 0) { result.append(string); } i++; } return result.toString(); } return nodeset; } public ModelElementBindSimple getAnotherMeb() { return anotherMeb; } public void setAnotherMeb(ModelElementBindSimple anotherMeb) { this.anotherMeb = anotherMeb; } /** * Sauvegarde la contrainte (sans parenthses englobantes) sur la longueur fournie. Ensuite, * appelle setConstraint pour prendre en compte la contrainte longueur dans l'attribut * "constraint" du meb. Si le field associ n'est pas required, la contrainte longueur transmise * setConstraint est modifie de faon autoriser les chanes vides. * * @param lengthConstraint * the constraint with min-length and max-length */ public void setLengthConstraint(String lengthConstraint) { this.lengthConstraint = "(" + lengthConstraint + ")"; if (isRequired()) { setConstraint(this.lengthConstraint); } else { setConstraint("((string-length(.) = 0) or " + this.lengthConstraint + ")"); } } /** * @return the lengthConstraint */ public String getLengthConstraint() { return lengthConstraint; } /** * @return */ public boolean isRepeaterRootBind() { return isRepeaterRootBind; } /** * @param isRepeaterRootBind */ public void setRepeaterRootBind(boolean isRepeaterRootBind) { this.isRepeaterRootBind = isRepeaterRootBind; } /** * @return the isAnAssociation */ public boolean isAnAssociation() { return isAnAssociation; } /** * @param isAnAssociation * the isAnAssociation to set */ public void setAnAssociation(boolean isAnAssociation) { this.isAnAssociation = isAnAssociation; } /** * @param multipleInputReference * the multipleInputReference to set */ public void setMultipleInputReference(String multipleInputReference) { this.multipleInputReference = multipleInputReference; } /** * @return the multipleInputReference */ private String getMultipleInputReference() { return multipleInputReference; } }