0001: /*
0002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
0003: * Distributed under the terms of either:
0004: * - the common development and distribution license (CDDL), v1.0; or
0005: * - the GNU Lesser General Public License, v2.1 or later
0006: * $Id: FormBuilderXhtml.java 3819 2007-06-28 13:13:23Z gbevin $
0007: */
0008: package com.uwyn.rife.site;
0009:
0010: import com.uwyn.rife.tools.*;
0011: import java.util.*;
0012:
0013: import com.uwyn.rife.template.Template;
0014: import com.uwyn.rife.template.TemplateFactory;
0015: import com.uwyn.rife.template.exceptions.TemplateException;
0016: import com.uwyn.rife.tools.exceptions.BeanUtilsException;
0017: import java.beans.PropertyDescriptor;
0018: import java.lang.reflect.InvocationTargetException;
0019: import java.util.logging.Logger;
0020:
0021: public class FormBuilderXhtml implements FormBuilder {
0022: public static final String VALUE_SELECTED = " selected=\"selected\"";
0023: public static final String VALUE_CHECKED = " checked=\"checked\"";
0024:
0025: private static final String ID_NAME = "NAME";
0026: private static final String ID_ATTRIBUTES = "ATTRIBUTES";
0027: private static final String ID_VALUE = "VALUE";
0028: private static final String ID_MAXLENGTH = "MAXLENGTH";
0029: private static final String ID_CHECKED = "CHECKED";
0030: private static final String ID_OPTIONS = "OPTIONS";
0031: private static final String ID_SELECTED = "SELECTED";
0032: private static final String ID_LABEL = "LABEL";
0033: private static final String ID_DISABLED = "DISABLED";
0034:
0035: public static final String FORM_OPTION = "FORM:OPTION:";
0036:
0037: private ValidationBuilder mValidationBuilder = new ValidationBuilderXhtml();
0038:
0039: public Collection<String> generateForm(Template template,
0040: Class beanClass, Map<String, String[]> values, String prefix)
0041: throws BeanUtilsException {
0042: if (null == beanClass) {
0043: return Collections.EMPTY_LIST;
0044: }
0045:
0046: // create an instance of the bean
0047: Object bean;
0048: try {
0049: bean = beanClass.newInstance();
0050: } catch (Throwable e) {
0051: bean = null;
0052: }
0053:
0054: return generateForm(template, beanClass, bean, values, prefix);
0055: }
0056:
0057: public Collection<String> generateForm(Template template,
0058: Object bean, Map<String, String[]> values, String prefix)
0059: throws BeanUtilsException {
0060: if (null == bean) {
0061: return Collections.EMPTY_LIST;
0062: }
0063:
0064: if (bean instanceof Class)
0065: throw new IllegalArgumentException(
0066: "bean should be a bean instance, not a bean class.");
0067:
0068: return generateForm(template, bean.getClass(), bean, values,
0069: prefix);
0070: }
0071:
0072: private Collection<String> generateForm(final Template template,
0073: Class beanClass, Object bean,
0074: final Map<String, String[]> values, final String prefix)
0075: throws BeanUtilsException {
0076: final ArrayList<String> set_values = new ArrayList<String>();
0077:
0078: if (null == template) {
0079: return set_values;
0080: }
0081:
0082: if (null == bean) {
0083: // generate the form fields using the provided value map to set the
0084: // default values for the fields
0085: BeanUtils.processProperties(beanClass, null, null, null,
0086: new BeanPropertyProcessor() {
0087: public boolean gotProperty(String name,
0088: PropertyDescriptor descriptor)
0089: throws IllegalAccessException,
0090: IllegalArgumentException,
0091: InvocationTargetException {
0092: String[] property_values = null;
0093: if (values != null) {
0094: if (null == prefix) {
0095: property_values = values.get(name);
0096: } else {
0097: property_values = values.get(prefix
0098: + name);
0099: }
0100: }
0101:
0102: generateFormField(template, null,
0103: descriptor.getPropertyType(), name,
0104: property_values, prefix, set_values);
0105:
0106: return true;
0107: }
0108: });
0109: } else {
0110: // check if the bean is constrained
0111: final Constrained constrained = ConstrainedUtils
0112: .makeConstrainedInstance(bean);
0113:
0114: Validated validated = null;
0115:
0116: final Set<ValidationError> previous_errors;
0117: if (null == values) {
0118: // check if the bean is validated
0119: if (bean instanceof Validated) {
0120: validated = (Validated) bean;
0121:
0122: // check if validation errors are already present in the bean,
0123: // and generate the formatted errors
0124: set_values.addAll(mValidationBuilder
0125: .generateValidationErrors(template,
0126: validated.getValidationErrors(),
0127: validated.getValidatedSubjects(),
0128: prefix));
0129: set_values.addAll(mValidationBuilder
0130: .generateErrorMarkings(template, validated
0131: .getValidationErrors(), validated
0132: .getValidatedSubjects(), prefix));
0133:
0134: // store the validation errors and revalidate
0135: previous_errors = validated.getValidationErrors();
0136:
0137: // revalidate the bean to check which fields have to be displayed
0138: validated.resetValidation();
0139: validated.validate();
0140: } else {
0141: previous_errors = null;
0142: }
0143: } else {
0144: previous_errors = null;
0145: }
0146:
0147: // generate the form fields using the bean's property values to set
0148: // the default values for the fields
0149: BeanUtils.processPropertyValues(bean, null, null, null,
0150: new BeanPropertyValueProcessor() {
0151: public void gotProperty(String name,
0152: PropertyDescriptor descriptor,
0153: Object value)
0154: throws IllegalAccessException,
0155: IllegalArgumentException,
0156: InvocationTargetException {
0157: String[] property_values = null;
0158: ConstrainedProperty constrained_property = null;
0159:
0160: // get the corresponding constrained property, if it exists
0161: if (constrained != null) {
0162: constrained_property = constrained
0163: .getConstrainedProperty(name);
0164: }
0165:
0166: // check if the bean is validated and if the validation error for the
0167: // property contains an erroneous value, in that case this value will
0168: // be used instead, since it contains the exact cause of the error.
0169: if (previous_errors != null
0170: && previous_errors.size() > 0) {
0171: for (ValidationError error : previous_errors) {
0172: if (error.getErroneousValue() != null
0173: && error.getSubject()
0174: .equals(name)) {
0175: property_values = ArrayUtils
0176: .createStringArray(
0177: error
0178: .getErroneousValue(),
0179: constrained_property);
0180: break;
0181: }
0182: }
0183: }
0184:
0185: if (values != null) {
0186: if (null == prefix) {
0187: property_values = values.get(name);
0188: } else {
0189: property_values = values.get(prefix
0190: + name);
0191: }
0192: } else {
0193: // if no erroneous value could be obtained, create a string
0194: // representation of the property value
0195: if (null == property_values) {
0196: if (null == value) {
0197: property_values = null;
0198: } else {
0199: property_values = ArrayUtils
0200: .createStringArray(
0201: value,
0202: constrained_property);
0203: }
0204: }
0205: }
0206:
0207: // generate the form field
0208: generateFormField(template, constrained,
0209: descriptor.getPropertyType(), name,
0210: property_values, prefix, set_values);
0211: }
0212: });
0213:
0214: if (validated != null) {
0215: // restore the previous validation errors
0216: validated.replaceValidationErrors(previous_errors);
0217: }
0218: }
0219:
0220: return set_values;
0221: }
0222:
0223: private void generateFormField(Template template,
0224: Constrained constrained, Class propertyType,
0225: String propertyName, String[] propertyValues,
0226: String prefix, ArrayList<String> setValues) {
0227: ConstrainedProperty constrained_property = null;
0228:
0229: if (constrained != null) {
0230: constrained_property = constrained
0231: .getConstrainedProperty(propertyName);
0232: }
0233:
0234: if (null == constrained_property) {
0235: generateField(template, null, propertyType, propertyName,
0236: propertyValues, prefix, setValues, false);
0237: } else {
0238: generateField(template, null, propertyType,
0239: constrained_property, propertyValues, prefix,
0240: setValues, false);
0241: }
0242: }
0243:
0244: public Collection<String> generateField(Template template,
0245: ConstrainedProperty property, String[] values, String prefix) {
0246: return generateField(template, null, null, property, values,
0247: prefix, null, false);
0248: }
0249:
0250: public Collection<String> generateField(Template template,
0251: Class propertyType, ConstrainedProperty property,
0252: String[] values, String prefix) {
0253: return generateField(template, null, propertyType, property,
0254: values, prefix, null, false);
0255: }
0256:
0257: public Collection<String> replaceField(Template template,
0258: String templateFieldName, ConstrainedProperty property,
0259: String[] values, String prefix) {
0260: return generateField(template, templateFieldName, null,
0261: property, values, prefix, null, true);
0262: }
0263:
0264: public Collection<String> replaceField(Template template,
0265: String templateFieldName, Class propertyType,
0266: ConstrainedProperty property, String[] values, String prefix) {
0267: return generateField(template, templateFieldName, propertyType,
0268: property, values, prefix, null, true);
0269: }
0270:
0271: private Collection<String> generateField(Template template,
0272: String templateFieldName, Class propertyType,
0273: ConstrainedProperty property, String[] values,
0274: String prefix, ArrayList<String> setValues,
0275: boolean replaceExistingValues) {
0276: if (null == setValues) {
0277: setValues = new ArrayList<String>();
0278: }
0279:
0280: if (null == template || null == property) {
0281: return setValues;
0282: }
0283:
0284: String name;
0285: if (null == prefix) {
0286: name = property.getPropertyName();
0287: } else {
0288: name = prefix + property.getPropertyName();
0289: }
0290:
0291: if (null == templateFieldName) {
0292: templateFieldName = name;
0293: }
0294:
0295: generateField(template, templateFieldName, propertyType, name,
0296: property, values, setValues, replaceExistingValues);
0297:
0298: return setValues;
0299: }
0300:
0301: public Collection<String> generateField(Template template,
0302: String name, String[] values, String prefix) {
0303: return generateField(template, null, null, name, values,
0304: prefix, null, false);
0305: }
0306:
0307: public Collection<String> generateField(Template template,
0308: Class propertyType, String name, String[] values,
0309: String prefix) {
0310: return generateField(template, null, propertyType, name,
0311: values, prefix, null, false);
0312: }
0313:
0314: public Collection<String> replaceField(Template template,
0315: String templateFieldName, String name, String[] values,
0316: String prefix) {
0317: return generateField(template, templateFieldName, null, name,
0318: values, prefix, null, true);
0319: }
0320:
0321: public Collection<String> replaceField(Template template,
0322: String templateFieldName, Class propertyType, String name,
0323: String[] values, String prefix) {
0324: return generateField(template, templateFieldName, propertyType,
0325: name, values, prefix, null, true);
0326: }
0327:
0328: private Collection<String> generateField(Template template,
0329: String templateFieldName, Class propertyType, String name,
0330: String[] values, String prefix,
0331: ArrayList<String> setValues, boolean replaceExistingValues) {
0332: if (null == setValues) {
0333: setValues = new ArrayList<String>();
0334: }
0335:
0336: if (null == template || null == name || 0 == name.length()) {
0337: return setValues;
0338: }
0339:
0340: if (prefix != null) {
0341: name = prefix + name;
0342: }
0343:
0344: if (null == templateFieldName) {
0345: templateFieldName = name;
0346: }
0347:
0348: generateField(template, templateFieldName, propertyType, name,
0349: null, values, setValues, replaceExistingValues);
0350:
0351: return setValues;
0352: }
0353:
0354: private void generateField(Template template,
0355: String templateFieldName, Class propertyType, String name,
0356: ConstrainedProperty property, String[] values,
0357: ArrayList<String> setValues, boolean replaceExistingValues) {
0358: Template builder_template = TemplateFactory.XHTML
0359: .get("formbuilder.fields");
0360:
0361: generateFieldHidden(template, templateFieldName, name,
0362: property, values, builder_template, setValues,
0363: replaceExistingValues);
0364: generateFieldInput(template, templateFieldName, name, property,
0365: values, builder_template, setValues,
0366: replaceExistingValues);
0367: generateFieldSecret(template, templateFieldName, name,
0368: property, values, builder_template, setValues,
0369: replaceExistingValues);
0370: generateFieldTextarea(template, templateFieldName, name,
0371: property, values, builder_template, setValues,
0372: replaceExistingValues);
0373: generateFieldRadio(template, templateFieldName, propertyType,
0374: name, property, values, builder_template, setValues,
0375: replaceExistingValues);
0376: generateFieldCheckbox(template, templateFieldName,
0377: propertyType, name, property, values, builder_template,
0378: setValues, replaceExistingValues);
0379: generateFieldSelect(template, templateFieldName, propertyType,
0380: name, property, values, builder_template, setValues,
0381: replaceExistingValues);
0382: generateFieldDisplay(template, templateFieldName, propertyType,
0383: name, property, values, builder_template, setValues,
0384: replaceExistingValues);
0385: }
0386:
0387: private void generateFieldText(String prefix, boolean setValue,
0388: boolean valueAsAttribute, boolean limitLength,
0389: boolean disableField, Template template,
0390: String templateFieldName, String name,
0391: ConstrainedProperty property, String[] values,
0392: Template builderTemplate, ArrayList<String> setValues,
0393: boolean replaceExistingValues) {
0394: StringBuilder field_buffer;
0395: String field;
0396: String field_attributes;
0397:
0398: field_buffer = new StringBuilder(prefix.length()
0399: + templateFieldName.length());
0400: field_buffer.append(prefix);
0401: field_buffer.append(templateFieldName);
0402: field = field_buffer.toString();
0403:
0404: if (template.hasValueId(field)
0405: && (replaceExistingValues || !template
0406: .isValueSet(field))) {
0407: field_buffer = new StringBuilder(prefix.length()
0408: + MIDDLE_ATTRIBUTES.length()
0409: + templateFieldName.length());
0410: field_buffer.append(prefix);
0411: field_buffer.append(MIDDLE_ATTRIBUTES);
0412: field_buffer.append(templateFieldName);
0413: field_attributes = field_buffer.toString();
0414:
0415: // set the field name
0416: builderTemplate.setValue(ID_NAME, template.getEncoder()
0417: .encode(name));
0418:
0419: // determine the value by using the provided value or apply the
0420: // default value if it has been set in the ConstrainedProperty
0421: String value = null;
0422: if (values != null && values.length > 0
0423: && values[0] != null) {
0424: value = template.getEncoder().encode(values[0]);
0425: } else if (property != null && property.hasDefaultValue()) {
0426: value = template.getEncoder().encode(
0427: property.getDefaultValue().toString());
0428: }
0429:
0430: // set the attributes that the user provided through a block value
0431: if (template.hasBlock(field_attributes)) {
0432: // try to set the name if a placeholder is available for it
0433: if (template.hasValueId(ID_FORM_NAME)) {
0434: template.setValue(ID_FORM_NAME, template
0435: .getEncoder().encode(name));
0436: }
0437:
0438: // try to set the value if a placeholder is available for it
0439: if (template.hasValueId(ID_FORM_VALUE) && value != null) {
0440: template.setValue(ID_FORM_VALUE, value);
0441: }
0442:
0443: builderTemplate.setValue(ID_ATTRIBUTES, " "
0444: + template.getBlock(field_attributes).trim());
0445:
0446: // remove the values that were set
0447: if (template.hasValueId(ID_FORM_NAME)) {
0448: template.removeValue(ID_FORM_NAME);
0449: }
0450: if (template.hasValueId(ID_FORM_VALUE)) {
0451: template.removeValue(ID_FORM_VALUE);
0452: }
0453: }
0454: // set the attributes that the user provided through a default value
0455: else if (template.hasDefaultValue(field)) {
0456: builderTemplate.setValue(ID_ATTRIBUTES, " "
0457: + template.getDefaultValue(field).trim());
0458: }
0459:
0460: // set the provided value or apply the default value if it has been
0461: // set in the ConstrainedProperty
0462: if (setValue && value != null) {
0463: builderTemplate.setValue(ID_VALUE, value);
0464: if (valueAsAttribute) {
0465: builderTemplate
0466: .appendBlock(ID_ATTRIBUTES, ID_VALUE);
0467: }
0468: }
0469:
0470: // handle the length limit if it has been set in the
0471: // ConstrainedProperty
0472: if (limitLength && property != null
0473: && property.getMaxLength() >= 0) {
0474: builderTemplate.setValue(ID_MAXLENGTH, property
0475: .getMaxLength());
0476: builderTemplate
0477: .appendBlock(ID_ATTRIBUTES, ID_MAXLENGTH);
0478: }
0479:
0480: // set the field to disabled if the ConstrainedProperty is not
0481: // editable
0482: if (disableField && property != null
0483: && !property.isEditable()) {
0484: builderTemplate.appendBlock(ID_ATTRIBUTES, ID_DISABLED);
0485: }
0486:
0487: // replace the form field tag in the provided template by the
0488: // newly constructed functional form field
0489: template.setValue(field, builderTemplate.getBlock(prefix));
0490:
0491: // register the form fields tag in the list of value ids that
0492: // have been set
0493: setValues.add(field);
0494:
0495: // clear out template
0496: builderTemplate.removeValue(ID_NAME);
0497: builderTemplate.removeValue(ID_VALUE);
0498: builderTemplate.removeValue(ID_MAXLENGTH);
0499: builderTemplate.removeValue(ID_ATTRIBUTES);
0500: }
0501: }
0502:
0503: private void generateFieldHidden(Template template,
0504: String templateFieldName, String name,
0505: ConstrainedProperty property, String[] values,
0506: Template builderTemplate, ArrayList<String> setValues,
0507: boolean replaceExistingValues) {
0508: generateFieldText(PREFIX_FORM_HIDDEN, true, true, false, false,
0509: template, templateFieldName, name, property, values,
0510: builderTemplate, setValues, replaceExistingValues);
0511: }
0512:
0513: private void generateFieldInput(Template template,
0514: String templateFieldName, String name,
0515: ConstrainedProperty property, String[] values,
0516: Template builderTemplate, ArrayList<String> setValues,
0517: boolean replaceExistingValues) {
0518: generateFieldText(PREFIX_FORM_INPUT, true, true, true, true,
0519: template, templateFieldName, name, property, values,
0520: builderTemplate, setValues, replaceExistingValues);
0521: }
0522:
0523: private void generateFieldSecret(Template template,
0524: String templateFieldName, String name,
0525: ConstrainedProperty property, String[] values,
0526: Template builderTemplate, ArrayList<String> setValues,
0527: boolean replaceExistingValues) {
0528: generateFieldText(PREFIX_FORM_SECRET, false, true, true, true,
0529: template, templateFieldName, name, property, values,
0530: builderTemplate, setValues, replaceExistingValues);
0531: }
0532:
0533: private void generateFieldTextarea(Template template,
0534: String templateFieldName, String name,
0535: ConstrainedProperty property, String[] values,
0536: Template builderTemplate, ArrayList<String> setValues,
0537: boolean replaceExistingValues) {
0538: generateFieldText(PREFIX_FORM_TEXTAREA, true, false, false,
0539: true, template, templateFieldName, name, property,
0540: values, builderTemplate, setValues,
0541: replaceExistingValues);
0542: }
0543:
0544: private void generateFieldCollection(String prefix,
0545: boolean singleValue, Template template,
0546: String templateFieldName, Class propertyType, String name,
0547: ConstrainedProperty property, String[] values,
0548: Template builderTemplate, ArrayList<String> setValues,
0549: boolean replaceExistingValues) {
0550: StringBuilder field_buffer;
0551: String field;
0552: String field_attributes;
0553:
0554: // handle input form fields
0555: field_buffer = new StringBuilder(prefix.length()
0556: + templateFieldName.length());
0557: field_buffer.append(prefix);
0558: field_buffer.append(templateFieldName);
0559: field = field_buffer.toString();
0560:
0561: if (template.hasValueId(field)
0562: && (replaceExistingValues || !template
0563: .isValueSet(field))) {
0564: if (replaceExistingValues) {
0565: template.blankValue(field);
0566: }
0567:
0568: field_buffer = new StringBuilder(prefix.length()
0569: + MIDDLE_ATTRIBUTES.length()
0570: + templateFieldName.length());
0571: field_buffer.append(prefix);
0572: field_buffer.append(MIDDLE_ATTRIBUTES);
0573: field_buffer.append(templateFieldName);
0574: field_attributes = field_buffer.toString();
0575:
0576: // set the field name
0577: builderTemplate.setValue(ID_NAME, template.getEncoder()
0578: .encode(name));
0579:
0580: // setup the active values
0581: ArrayList<String> active_values = null;
0582: if (values != null && values.length > 0) {
0583: if (singleValue) {
0584: if (values[0] != null) {
0585: active_values = new ArrayList<String>();
0586: active_values.add(values[0]);
0587: }
0588: } else {
0589: active_values = new ArrayList<String>();
0590: for (String value : values) {
0591: if (null == value) {
0592: continue;
0593: }
0594: active_values.add(value);
0595: }
0596: }
0597: }
0598: if (null == active_values && property != null
0599: && property.hasDefaultValue()) {
0600: active_values = new ArrayList<String>();
0601: active_values
0602: .add(property.getDefaultValue().toString());
0603: }
0604:
0605: String[] list_values = null;
0606:
0607: // obtain the list of possible values for properties that are constrained to a list
0608: if (property != null && property.isInList()) {
0609: list_values = property.getInList();
0610: }
0611: // obtain the list of possible values for enum properties
0612: else if (propertyType != null) {
0613: if (propertyType.isEnum()) {
0614: list_values = ClassUtils
0615: .getEnumClassValues(propertyType);
0616: } else if (propertyType.isArray()
0617: && propertyType.getComponentType().isEnum()) {
0618: list_values = ClassUtils
0619: .getEnumClassValues(propertyType
0620: .getComponentType());
0621: }
0622: }
0623:
0624: // if no list has been defined for the constrained property, just
0625: // set one tag without any additional attributes
0626: if (null == list_values) {
0627: // set the attributes that the user provided through a default value
0628: if (template.hasBlock(field_attributes)) {
0629: // try to set the name if a placeholder is available for it
0630: if (template.hasValueId(ID_FORM_NAME)) {
0631: template.setValue(ID_FORM_NAME, template
0632: .getEncoder().encode(name));
0633: }
0634:
0635: // try to set the value if a placeholder is available for it
0636: if (template.hasValueId(ID_FORM_VALUE)) {
0637: if (values != null && values.length > 0
0638: && values[0] != null) {
0639: template.setValue(ID_FORM_VALUE, template
0640: .getEncoder().encode(values[0]));
0641: } else if (property != null
0642: && property.hasDefaultValue()) {
0643: template.setValue(ID_FORM_VALUE, template
0644: .getEncoder().encode(
0645: property.getDefaultValue()
0646: .toString()));
0647: }
0648: }
0649:
0650: builderTemplate.setValue(ID_ATTRIBUTES, " "
0651: + template.getBlock(field_attributes)
0652: .trim());
0653:
0654: // remove the values that were set
0655: if (template.hasValueId(ID_FORM_NAME)) {
0656: template.removeValue(ID_FORM_NAME);
0657: }
0658: if (template.hasValueId(ID_FORM_VALUE)) {
0659: template.removeValue(ID_FORM_VALUE);
0660: }
0661: } else if (template.hasDefaultValue(field)) {
0662: builderTemplate.setValue(ID_ATTRIBUTES, " "
0663: + template.getDefaultValue(field).trim());
0664: } else {
0665: builderTemplate.setValue(ID_ATTRIBUTES, "");
0666: }
0667:
0668: // check the field if the first value is active
0669: if (active_values != null
0670: && StringUtils.convertToBoolean(active_values
0671: .get(0))) {
0672: builderTemplate.appendBlock(ID_ATTRIBUTES,
0673: ID_CHECKED);
0674: }
0675:
0676: // set the field to disabled if the ConstrainedProperty is not
0677: // editable
0678: if (property != null && !property.isEditable()) {
0679: builderTemplate.appendBlock(ID_ATTRIBUTES,
0680: ID_DISABLED);
0681: }
0682:
0683: template.setValue(field, builderTemplate
0684: .getBlock(prefix));
0685: } else {
0686: for (String value : list_values) {
0687: if (null == value) {
0688: continue;
0689: }
0690:
0691: // try to set the name if a placeholder is available for it
0692: if (template.hasValueId(ID_FORM_NAME)) {
0693: template.setValue(ID_FORM_NAME, template
0694: .getEncoder().encode(name));
0695: }
0696:
0697: // try to set the value if a placeholder is available for it
0698: if (template.hasValueId(ID_FORM_VALUE)) {
0699: template.setValue(ID_FORM_VALUE, template
0700: .getEncoder().encode(value));
0701: }
0702:
0703: // set the attributes that the user provided through a default value
0704: if (template.hasBlock(field_attributes)) {
0705: builderTemplate.setValue(ID_ATTRIBUTES, " "
0706: + template.getBlock(field_attributes)
0707: .trim());
0708: } else if (template.hasDefaultValue(field)) {
0709: builderTemplate.setValue(ID_ATTRIBUTES, " "
0710: + template.getDefaultValue(field)
0711: .trim());
0712: } else {
0713: builderTemplate.setValue(ID_ATTRIBUTES, "");
0714: }
0715:
0716: // set the value of the field entry
0717: builderTemplate.setValue(ID_VALUE, template
0718: .getEncoder().encode(value));
0719: builderTemplate
0720: .appendBlock(ID_ATTRIBUTES, ID_VALUE);
0721:
0722: // set the field entry that corresponds to the active value
0723: if (active_values != null
0724: && active_values.contains(value)) {
0725: builderTemplate.appendBlock(ID_ATTRIBUTES,
0726: ID_CHECKED);
0727: }
0728:
0729: // set the field to disabled if the ConstrainedProperty is not
0730: // editable
0731: if (property != null && !property.isEditable()) {
0732: builderTemplate.appendBlock(ID_ATTRIBUTES,
0733: ID_DISABLED);
0734: }
0735:
0736: // check if this field entry has a custom layout
0737: if (template.hasBlock(field)) {
0738: // try to set the field if a placeholder is available for it
0739: if (template.hasValueId(ID_FORM_FIELD)) {
0740: template.setValue(ID_FORM_FIELD,
0741: builderTemplate.getBlock(prefix));
0742: }
0743:
0744: // try to set the label if a placeholder is available for it
0745: if (template.hasValueId(ID_FORM_LABEL)) {
0746: template.setValue(ID_FORM_LABEL,
0747: generateLabel(template,
0748: templateFieldName, value));
0749: }
0750:
0751: // append a new field entry button
0752: template.appendBlock(field, field);
0753:
0754: // clear the template
0755: if (template.hasValueId(ID_FORM_FIELD)) {
0756: template.removeValue(ID_FORM_FIELD);
0757: }
0758: if (template.hasValueId(ID_FORM_LABEL)) {
0759: template.removeValue(ID_FORM_LABEL);
0760: }
0761: }
0762: // there's no custom layout, put the label to the right
0763: // of the field entry
0764: else {
0765: // append a new field entry
0766: template.appendValue(field, builderTemplate
0767: .getBlock(prefix));
0768:
0769: // append the custom label if it's available
0770: template.appendValue(field, generateLabel(
0771: template, templateFieldName, value));
0772: }
0773:
0774: // remove the values that were set
0775: if (template.hasValueId(ID_FORM_NAME)) {
0776: template.removeValue(ID_FORM_NAME);
0777: }
0778: if (template.hasValueId(ID_FORM_VALUE)) {
0779: template.removeValue(ID_FORM_VALUE);
0780: }
0781: }
0782: }
0783:
0784: // register the form fields tag in the list of value ids that
0785: // have been set
0786: setValues.add(field);
0787:
0788: // clear out template
0789: builderTemplate.removeValue(ID_NAME);
0790: builderTemplate.removeValue(ID_VALUE);
0791: builderTemplate.removeValue(ID_ATTRIBUTES);
0792: }
0793: }
0794:
0795: private void generateFieldRadio(Template template,
0796: String templateFieldName, Class propertyType, String name,
0797: ConstrainedProperty property, String[] values,
0798: Template builderTemplate, ArrayList<String> setValues,
0799: boolean replaceExistingValues) {
0800: generateFieldCollection(PREFIX_FORM_RADIO, true, template,
0801: templateFieldName, propertyType, name, property,
0802: values, builderTemplate, setValues,
0803: replaceExistingValues);
0804: }
0805:
0806: private void generateFieldCheckbox(Template template,
0807: String templateFieldName, Class propertyType, String name,
0808: ConstrainedProperty property, String[] values,
0809: Template builderTemplate, ArrayList<String> setValues,
0810: boolean replaceExistingValues) {
0811: generateFieldCollection(PREFIX_FORM_CHECKBOX, false, template,
0812: templateFieldName, propertyType, name, property,
0813: values, builderTemplate, setValues,
0814: replaceExistingValues);
0815: }
0816:
0817: private void generateFieldSelect(Template template,
0818: String templateFieldName, Class propertyType, String name,
0819: ConstrainedProperty property, String[] values,
0820: Template builderTemplate, ArrayList<String> setValues,
0821: boolean replaceExistingValues) {
0822: StringBuilder field_buffer;
0823: String field;
0824:
0825: // handle input form fields
0826: field_buffer = new StringBuilder(PREFIX_FORM_SELECT.length()
0827: + templateFieldName.length());
0828: field_buffer.append(PREFIX_FORM_SELECT);
0829: field_buffer.append(templateFieldName);
0830: field = field_buffer.toString();
0831:
0832: if (template.hasValueId(field)
0833: && (replaceExistingValues || !template
0834: .isValueSet(field))) {
0835: // set the field name
0836: builderTemplate.setValue(ID_NAME, template.getEncoder()
0837: .encode(name));
0838:
0839: // setup the active values
0840: ArrayList<String> active_values = null;
0841: if (values != null && values.length > 0) {
0842: active_values = new ArrayList<String>();
0843: for (String value : values) {
0844: if (null == value) {
0845: continue;
0846: }
0847: active_values.add(value);
0848: }
0849: }
0850: if (null == active_values && property != null
0851: && property.hasDefaultValue()) {
0852: active_values = new ArrayList<String>();
0853: active_values
0854: .add(property.getDefaultValue().toString());
0855: }
0856:
0857: String[] list_values = null;
0858:
0859: // setup a select field options for constrained properties that
0860: // are constrained to a list
0861: if (property != null && property.isInList()) {
0862: list_values = property.getInList();
0863: }
0864: // setup a select field options for enum properties
0865: else if (propertyType != null) {
0866: if (propertyType.isEnum()) {
0867: list_values = ClassUtils
0868: .getEnumClassValues(propertyType);
0869: } else if (propertyType.isArray()
0870: && propertyType.getComponentType().isEnum()) {
0871: list_values = ClassUtils
0872: .getEnumClassValues(propertyType
0873: .getComponentType());
0874: }
0875: }
0876:
0877: if (list_values != null) {
0878: List<String> list = Arrays.asList(list_values);
0879:
0880: String default_value = null;
0881: if (property != null && property.hasDefaultValue()) {
0882: default_value = Convert.toString(property
0883: .getDefaultValue());
0884: if (list.contains(default_value)) {
0885: default_value = null;
0886: }
0887: }
0888:
0889: // setup the select options
0890: int i = 0;
0891: while (i < list.size()) {
0892: String value;
0893: if (default_value != null) {
0894: value = default_value;
0895: default_value = null;
0896: } else {
0897: value = list.get(i);
0898: i++;
0899: }
0900:
0901: if (null == value) {
0902: continue;
0903: }
0904:
0905: // set the value of the field entry
0906: builderTemplate.setValue(ID_VALUE, template
0907: .getEncoder().encode(value));
0908:
0909: // set the field entry that corresponds to the active value
0910: if (active_values != null
0911: && active_values.contains(value)) {
0912: builderTemplate.setBlock(ID_ATTRIBUTES,
0913: ID_SELECTED);
0914: } else {
0915: builderTemplate.setValue(ID_ATTRIBUTES, "");
0916: }
0917:
0918: builderTemplate.setValue(ID_LABEL, generateLabel(
0919: template, templateFieldName, value));
0920:
0921: // append a new option
0922: builderTemplate
0923: .appendBlock(ID_OPTIONS, FORM_OPTION);
0924:
0925: // clear the option values
0926: builderTemplate.removeValue(ID_ATTRIBUTES);
0927: builderTemplate.removeValue(ID_VALUE);
0928: builderTemplate.removeValue(ID_LABEL);
0929: if (template.hasValueId(ID_FORM_NAME)) {
0930: template.removeValue(ID_FORM_NAME);
0931: }
0932: if (template.hasValueId(ID_FORM_VALUE)) {
0933: template.removeValue(ID_FORM_VALUE);
0934: }
0935: }
0936:
0937: // set the attributes that the user provided through a default value
0938: if (template.hasDefaultValue(field)) {
0939: builderTemplate.setValue(ID_ATTRIBUTES, " "
0940: + template.getDefaultValue(field).trim());
0941: } else {
0942: builderTemplate.setValue(ID_ATTRIBUTES, "");
0943: }
0944:
0945: // set the field to disabled if the ConstrainedProperty is not
0946: // editable
0947: if (property != null && !property.isEditable()) {
0948: builderTemplate.appendBlock(ID_ATTRIBUTES,
0949: ID_DISABLED);
0950: }
0951: }
0952:
0953: // set the select field
0954: template.setValue(field, builderTemplate
0955: .getBlock(PREFIX_FORM_SELECT));
0956:
0957: // register the form fields tag in the list of value ids that
0958: // have been set
0959: setValues.add(field);
0960:
0961: // clear out template
0962: builderTemplate.removeValue(ID_NAME);
0963: builderTemplate.removeValue(ID_OPTIONS);
0964: builderTemplate.removeValue(ID_ATTRIBUTES);
0965: }
0966: }
0967:
0968: private void generateFieldDisplay(Template template,
0969: String templateFieldName, Class propertyType, String name,
0970: ConstrainedProperty property, String[] values,
0971: Template builderTemplate, ArrayList<String> setValues,
0972: boolean replaceExistingValues) {
0973: StringBuilder field_buffer;
0974: String field;
0975: String field_attributes;
0976:
0977: field_buffer = new StringBuilder(PREFIX_FORM_DISPLAY.length()
0978: + templateFieldName.length());
0979: field_buffer.append(PREFIX_FORM_DISPLAY);
0980: field_buffer.append(templateFieldName);
0981: field = field_buffer.toString();
0982:
0983: if (template.hasValueId(field)
0984: && (replaceExistingValues || !template
0985: .isValueSet(field))) {
0986: if (replaceExistingValues) {
0987: template.blankValue(field);
0988: }
0989:
0990: field_buffer = new StringBuilder(PREFIX_FORM_DISPLAY
0991: .length()
0992: + MIDDLE_ATTRIBUTES.length()
0993: + templateFieldName.length());
0994: field_buffer.append(PREFIX_FORM_DISPLAY);
0995: field_buffer.append(MIDDLE_ATTRIBUTES);
0996: field_buffer.append(templateFieldName);
0997: field_attributes = field_buffer.toString();
0998:
0999: int counter = 0;
1000: do {
1001: // determine the value by using the provided value or apply the
1002: // default value if it has been set in the ConstrainedProperty
1003: String value = null;
1004: if (values != null && values.length > counter
1005: && values[counter] != null) {
1006: value = template.getEncoder().encode(
1007: values[counter]);
1008: } else if (property != null
1009: && property.hasDefaultValue()) {
1010: value = template.getEncoder().encode(
1011: property.getDefaultValue().toString());
1012: }
1013:
1014: // set the attributes that the user provided through a block value
1015: if (template.hasBlock(field_attributes)) {
1016: // try to set the name if a placeholder is available for it
1017: if (template.hasValueId(ID_FORM_NAME)) {
1018: template.setValue(ID_FORM_NAME, template
1019: .getEncoder().encode(name));
1020: }
1021:
1022: // try to set the value if a placeholder is available for it
1023: if (template.hasValueId(ID_FORM_VALUE)
1024: && value != null) {
1025: template.setValue(ID_FORM_VALUE, value);
1026: }
1027:
1028: builderTemplate.setValue(ID_ATTRIBUTES, " "
1029: + template.getBlock(field_attributes)
1030: .trim());
1031:
1032: // remove the values that were set
1033: if (template.hasValueId(ID_FORM_NAME)) {
1034: template.removeValue(ID_FORM_NAME);
1035: }
1036: if (template.hasValueId(ID_FORM_VALUE)) {
1037: template.removeValue(ID_FORM_VALUE);
1038: }
1039: }
1040: // set the attributes that the user provided through a default value
1041: else if (template.hasDefaultValue(field)) {
1042: builderTemplate.setValue(ID_ATTRIBUTES, " "
1043: + template.getDefaultValue(field).trim());
1044: }
1045:
1046: // set the provided value or apply the default value if it has been
1047: // set in the ConstrainedProperty
1048: if (value != null) {
1049: // if the field is a constrained property that is constrained
1050: // to a list, display the label instead of the value
1051: if ((property != null && property.isInList() || propertyType != null
1052: && (propertyType.isEnum() || propertyType
1053: .isArray()
1054: && propertyType.getComponentType()
1055: .isEnum()))) {
1056: builderTemplate.setValue(ID_VALUE,
1057: generateLabel(template,
1058: templateFieldName, value));
1059: } else {
1060: builderTemplate.setValue(ID_VALUE, value);
1061: }
1062: }
1063:
1064: // replace the form field tag in the provided template by the
1065: // newly constructed functional form field
1066: String field_content = builderTemplate
1067: .getBlock(PREFIX_FORM_DISPLAY);
1068: if (0 == counter) {
1069: template.setValue(field, field_content);
1070: } else {
1071: template.appendValue(field, field_content);
1072: }
1073: } while (values != null && values.length > 1
1074: && ++counter < values.length);
1075:
1076: // register the form fields tag in the list of value ids that
1077: // have been set
1078: setValues.add(field);
1079:
1080: // clear out template
1081: builderTemplate.removeValue(ID_VALUE);
1082: builderTemplate.removeValue(ID_ATTRIBUTES);
1083: }
1084: }
1085:
1086: private String generateLabel(Template template,
1087: String templateFieldName, String value)
1088: throws TemplateException {
1089: StringBuilder label_id_buffer;
1090: String label_id;
1091: StringBuilder label_valueid_buffer;
1092: String label_valueid;
1093:
1094: // create the label id
1095: label_id_buffer = new StringBuilder(templateFieldName.length()
1096: + 1 + value.length());
1097: label_id_buffer.append(templateFieldName);
1098: label_id_buffer.append(":");
1099: label_id_buffer.append(value);
1100: label_id = label_id_buffer.toString();
1101:
1102: // create the label value id
1103: label_valueid_buffer = new StringBuilder(PREFIX_FORM_LABEL
1104: .length()
1105: + label_id.length());
1106: label_valueid_buffer.append(PREFIX_FORM_LABEL);
1107: label_valueid_buffer.append(label_id);
1108: label_valueid = label_valueid_buffer.toString();
1109:
1110: String label = null;
1111:
1112: // set a custom label if it's available from the resourcebundle
1113: if (template.hasResourceBundles()) {
1114: for (ResourceBundle bundle : template.getResourceBundles()) {
1115: // obtain the configuration value
1116: try {
1117: label = bundle.getString(label_id);
1118: if (label != null) {
1119: label = template.getEncoder().encode(label);
1120: }
1121: break;
1122: } catch (MissingResourceException e) {
1123: // whenever a resource can't be found, just use the next one in the collection
1124: }
1125: }
1126: }
1127:
1128: // set a custom label if it's available from the template
1129: if (null == label && template.hasBlock(label_valueid)) {
1130: label = template.getBlock(label_valueid);
1131: }
1132:
1133: // otherwise use the value
1134: if (null == label) {
1135: label = value;
1136: }
1137:
1138: return label;
1139: }
1140:
1141: public void removeForm(Template template, Class beanClass,
1142: String prefix) throws BeanUtilsException {
1143: if (null == template || null == beanClass) {
1144: return;
1145: }
1146:
1147: // create an instance of the bean
1148: Object bean;
1149: try {
1150: bean = beanClass.newInstance();
1151: } catch (Throwable e) {
1152: bean = null;
1153: }
1154:
1155: // generate the form fields
1156: Set<String> property_names = BeanUtils.getPropertyNames(
1157: beanClass, null, null, null);
1158: for (String property_name : property_names) {
1159: removeField(template, property_name, prefix);
1160: }
1161:
1162: Validated validated;
1163: if (bean != null && bean instanceof Validated) {
1164: validated = (Validated) bean;
1165:
1166: mValidationBuilder.removeValidationErrors(template,
1167: validated.getValidatedSubjects(), prefix);
1168: mValidationBuilder.removeErrorMarkings(template, validated
1169: .getValidatedSubjects(), prefix);
1170: }
1171: }
1172:
1173: public void removeField(Template template, String name,
1174: String prefix) {
1175: if (null == template || null == name || 0 == name.length()) {
1176: return;
1177: }
1178:
1179: if (prefix != null) {
1180: name = prefix + name;
1181: }
1182:
1183: removeField(template, name);
1184: }
1185:
1186: public void removeField(Template template, String templateFieldName) {
1187: if (null == template || null == templateFieldName
1188: || 0 == templateFieldName.length()) {
1189: return;
1190: }
1191:
1192: String value_id;
1193: for (String value_prefix : VALUE_PREFIXES) {
1194: value_id = value_prefix + templateFieldName;
1195: if (template.isValueSet(value_id)) {
1196: template.removeValue(value_id);
1197: }
1198: }
1199: }
1200:
1201: public Collection<String> selectParameter(Template template,
1202: String name, String[] values) {
1203: ArrayList<String> set_values = new ArrayList<String>();
1204:
1205: if (null == template || null == name || 0 == name.length()
1206: || null == values || 0 == values.length) {
1207: return set_values;
1208: }
1209:
1210: StringBuilder value_id_buffer;
1211: String value_id;
1212: for (String value : values) {
1213: if (null == value) {
1214: continue;
1215: }
1216:
1217: value_id_buffer = new StringBuilder(name);
1218: value_id_buffer.append(":");
1219: value_id_buffer.append(value);
1220:
1221: value_id = value_id_buffer.toString() + SUFFIX_SELECTED;
1222: if (template.hasValueId(value_id)) {
1223: template.setValue(value_id, VALUE_SELECTED);
1224: set_values.add(value_id);
1225: }
1226:
1227: value_id = value_id_buffer.toString() + SUFFIX_CHECKED;
1228: if (template.hasValueId(value_id)) {
1229: template.setValue(value_id, VALUE_CHECKED);
1230: set_values.add(value_id);
1231: }
1232:
1233: value_id = name + SUFFIX_CHECKED;
1234: if (template.hasValueId(value_id)) {
1235: if (StringUtils.convertToBoolean(value)) {
1236: template.setValue(value_id, VALUE_CHECKED);
1237: set_values.add(value_id);
1238: }
1239: }
1240: }
1241:
1242: return set_values;
1243: }
1244:
1245: public void unselectParameter(Template template, String name,
1246: String[] values) {
1247: if (null == template || null == name || 0 == name.length()) {
1248: return;
1249: }
1250:
1251: String value_id;
1252:
1253: value_id = name + SUFFIX_CHECKED;
1254: if (template.hasValueId(value_id)) {
1255: template.removeValue(value_id);
1256: }
1257:
1258: if (null == values || 0 == values.length) {
1259: return;
1260: }
1261:
1262: StringBuilder value_id_buffer;
1263: for (String value : values) {
1264: if (null == value) {
1265: continue;
1266: }
1267:
1268: value_id_buffer = new StringBuilder(name);
1269: value_id_buffer.append(":");
1270: value_id_buffer.append(value);
1271:
1272: value_id = value_id_buffer.toString() + SUFFIX_SELECTED;
1273: if (template.hasValueId(value_id)) {
1274: template.removeValue(value_id);
1275: }
1276:
1277: value_id = value_id_buffer.toString() + SUFFIX_CHECKED;
1278: if (template.hasValueId(value_id)) {
1279: template.removeValue(value_id);
1280: }
1281: }
1282: }
1283:
1284: public ValidationBuilder getValidationBuilder() {
1285: return mValidationBuilder;
1286: }
1287:
1288: public Object clone() {
1289: try {
1290: FormBuilderXhtml other = (FormBuilderXhtml) super .clone();
1291:
1292: other.mValidationBuilder = (ValidationBuilder) this .mValidationBuilder
1293: .clone();
1294:
1295: return other;
1296: } catch (CloneNotSupportedException e) {
1297: ///CLOVER:OFF
1298: // this should never happen
1299: Logger.getLogger("com.uwyn.rife.site").severe(
1300: ExceptionUtils.getExceptionStackTrace(e));
1301: return null;
1302: ///CLOVER:ON
1303: }
1304: }
1305: }
|