001package org.andromda.cartridges.jsf2.metafacades;
002
003import java.util.Collection;
004import java.util.Iterator;
005import java.util.List;
006import org.andromda.cartridges.jsf2.JSFGlobals;
007import org.andromda.cartridges.jsf2.JSFProfile;
008import org.andromda.cartridges.jsf2.JSFUtils;
009import org.andromda.metafacades.uml.ClassifierFacade;
010import org.andromda.metafacades.uml.FrontEndAction;
011import org.andromda.metafacades.uml.FrontEndParameter;
012import org.andromda.metafacades.uml.FrontEndView;
013import org.andromda.metafacades.uml.ModelElementFacade;
014import org.andromda.metafacades.uml.ParameterFacade;
015import org.andromda.utils.StringUtilsHelper;
016import org.apache.commons.lang.ObjectUtils;
017import org.apache.commons.lang.StringUtils;
018
019/**
020 * MetafacadeLogic implementation for org.andromda.cartridges.jsf2.metafacades.JSFAttribute.
021 *
022 * @see JSFAttribute
023 */
024public class JSFAttributeLogicImpl
025    extends JSFAttributeLogic
026{
027    private static final long serialVersionUID = 34L;
028    /**
029     * @param metaObject
030     * @param context
031     */
032    public JSFAttributeLogicImpl(
033        Object metaObject,
034        String context)
035    {
036        super(metaObject, context);
037    }
038
039    /**
040     * @return messageKey
041     * @see JSFAttribute#getMessageKey()
042     */
043    protected String handleGetMessageKey()
044    {
045        final StringBuilder messageKey = new StringBuilder();
046        if (!this.isNormalizeMessages())
047        {
048            final ClassifierFacade owner = this.getOwner();
049            if (owner != null)
050            {
051                messageKey.append(StringUtilsHelper.toResourceMessageKey(owner.getName()));
052                messageKey.append('.');
053            }
054        }
055        final String name = this.getName();
056        if (name != null && name.trim().length() > 0)
057        {
058            messageKey.append(StringUtilsHelper.toResourceMessageKey(name));
059        }
060        return messageKey.toString();
061    }
062
063    /**
064     * Indicates whether or not we should normalize messages.
065     *
066     * @return true/false
067     */
068    private boolean isNormalizeMessages()
069    {
070        final String normalizeMessages =
071            ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.NORMALIZE_MESSAGES));
072        return Boolean.valueOf(normalizeMessages).booleanValue();
073    }
074
075    /**
076     * @return StringUtilsHelper.toPhrase(super.getName())
077     * @see JSFAttribute#getMessageValue()
078     */
079    protected String handleGetMessageValue()
080    {
081        return StringUtilsHelper.toPhrase(super.getName());
082    }
083
084    /**
085     * @return format
086     * @see JSFAttribute#getFormat()
087     */
088    protected String handleGetFormat()
089    {
090        return JSFUtils.getFormat(
091            (ModelElementFacade)this.THIS(),
092            this.getType(),
093            this.getDefaultDateFormat(),
094            this.getDefaultTimeFormat());
095    }
096
097    /**
098     * @return the default time format pattern as defined using the configured property
099     */
100    private String getDefaultTimeFormat()
101    {
102        return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_TIMEFORMAT);
103    }
104
105    /**
106     * @return the default date format pattern as defined using the configured property
107     */
108    private String getDefaultDateFormat()
109    {
110        return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_DATEFORMAT);
111    }
112
113    /**
114     * @return dummyValue
115     * @see JSFAttribute#getDummyValue()
116     */
117    protected String handleGetDummyValue()
118    {
119        final ClassifierFacade type = this.getType();
120        if (type != null)
121        {
122            final String typeName = type.getFullyQualifiedName();
123            final String name = this.getName();
124            if ("String".equals(typeName))
125            {
126                return "\"" + name + "-test" + "\"";
127            }
128            if ("java.util.Date".equals(typeName))
129            {
130                return "new java.util.Date()";
131            }
132            if ("java.sql.Date".equals(typeName))
133            {
134                return "new java.sql.Date(new java.util.Date().getTime())";
135            }
136            if ("java.sql.Timestamp".equals(typeName))
137            {
138                return "new java.sql.Timestamp(new Date().getTime())";
139            }
140            if ("java.util.Calendar".equals(typeName))
141            {
142                return "java.util.Calendar.getInstance()";
143            }
144            if ("int".equals(typeName))
145            {
146                return "(int)" + name.hashCode();
147            }
148            if ("boolean".equals(typeName))
149            {
150                return "false";
151            }
152            if ("long".equals(typeName))
153            {
154                return "(long)" + name.hashCode();
155            }
156            if ("char".equals(typeName))
157            {
158                return "(char)" + name.hashCode();
159            }
160            if ("float".equals(typeName))
161            {
162                return "(float)" + name.hashCode() / hashCode();
163            }
164            if ("double".equals(typeName))
165            {
166                return "(double)" + name.hashCode() / hashCode();
167            }
168            if ("short".equals(typeName))
169            {
170                return "(short)" + name.hashCode();
171            }
172            if ("byte".equals(typeName))
173            {
174                return "(byte)" + name.hashCode();
175            }
176            if ("java.lang.Integer".equals(typeName) || "Integer".equals(typeName))
177            {
178                return "new Integer((int)" + name.hashCode() + ")";
179            }
180            if ("java.lang.Boolean".equals(typeName) || "Boolean".equals(typeName))
181            {
182                return "Boolean.FALSE";
183            }
184            if ("java.lang.Long".equals(typeName) || "Long".equals(typeName))
185            {
186                return "new Long((long)" + name.hashCode() + ")";
187            }
188            if ("java.lang.Character".equals(typeName) || "Character".equals(typeName))
189            {
190                return "new Character(char)" + name.hashCode() + ")";
191            }
192            if ("java.lang.Float".equals(typeName) || "Float".equals(typeName))
193            {
194                return "new Float((float)" + name.hashCode() / hashCode() + ")";
195            }
196            if ("java.lang.Double".equals(typeName) || "Double".equals(typeName))
197            {
198                return "new Double((double)" + name.hashCode() / hashCode() + ")";
199            }
200            if ("java.lang.Short".equals(typeName) || "Short".equals(typeName))
201            {
202                return "new Short((short)" + name.hashCode() + ")";
203            }
204            if ("java.lang.Byte".equals(typeName) || "Byte".equals(typeName))
205            {
206                return "new Byte((byte)" + name.hashCode() + ")";
207            }
208
209            //if (type.isArrayType()) return constructDummyArray();
210            if (type.isSetType())
211            {
212                return "new java.util.HashSet(java.util.Arrays.asList(" + constructDummyArray() + "))";
213            }
214            if (type.isCollectionType())
215            {
216                return "java.util.Arrays.asList(" + constructDummyArray() + ")";
217            }
218
219            // maps and others types will simply not be treated
220        }
221        return "null";
222    }
223
224    /**
225     * Constructs a string representing an array initialization in Java.
226     *
227     * @return A String representing Java code for the initialization of an array.
228     */
229    private String constructDummyArray()
230    {
231        return JSFUtils.constructDummyArrayDeclaration(
232            this.getName(),
233            JSFGlobals.DUMMY_ARRAY_COUNT);
234    }
235
236    /**
237     * @param ownerParameter
238     * @return propertyName
239     * @see JSFAttribute#getFormPropertyName(org.andromda.metafacades.uml.ParameterFacade)
240     */
241    protected String handleGetFormPropertyName(final ParameterFacade ownerParameter)
242    {
243        final StringBuilder propertyName = new StringBuilder();
244        if (ownerParameter != null)
245        {
246            propertyName.append(ownerParameter.getName());
247            propertyName.append('.');
248        }
249        final String name = this.getName();
250        if (name != null && name.trim().length() > 0)
251        {
252            propertyName.append(name);
253        }
254        return propertyName.toString();
255    }
256
257    /**
258     * @param ownerParameter
259     * @return backingListName
260     * @see JSFAttribute#getBackingListName(org.andromda.metafacades.uml.ParameterFacade)
261     */
262    protected String handleGetBackingListName(final ParameterFacade ownerParameter)
263    {
264        final String backingListName =
265            StringUtils.replace(
266                ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_LIST_PATTERN)),
267                "{0}",
268                this.getFormPropertyId(ownerParameter));
269        return org.andromda.utils.StringUtilsHelper.lowerCamelCaseName(backingListName);
270    }
271
272    /**
273     * @param ownerParameter
274     * @return backingValueName
275     * @see JSFAttribute#getBackingValueName(org.andromda.metafacades.uml.ParameterFacade)
276     */
277    protected String handleGetBackingValueName(final ParameterFacade ownerParameter)
278    {
279        final String backingListName =
280            StringUtils.replace(
281                ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_VALUE_PATTERN)),
282                "{0}",
283                this.getFormPropertyId(ownerParameter));
284        return org.andromda.utils.StringUtilsHelper.lowerCamelCaseName(backingListName);
285    }
286
287    /**
288     * @param ownerParameter
289     * @return labelListName
290     * @see JSFAttribute#getLabelListName(org.andromda.metafacades.uml.ParameterFacade)
291     */
292    protected String handleGetLabelListName(final ParameterFacade ownerParameter)
293    {
294        return StringUtils.replace(
295            ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.LABEL_LIST_PATTERN)),
296            "{0}",
297            this.getFormPropertyId(ownerParameter));
298    }
299
300    /**
301     * @param ownerParameter
302     * @return valueListName
303     * @see JSFAttribute#getValueListName(org.andromda.metafacades.uml.ParameterFacade)
304     */
305    protected String handleGetValueListName(final ParameterFacade ownerParameter)
306    {
307        return StringUtils.replace(
308            ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.VALUE_LIST_PATTERN)),
309            "{0}",
310            this.getFormPropertyId(ownerParameter));
311    }
312
313    /**
314     * @param ownerParameter
315     * @return formPropertyId
316     * @see JSFAttribute#getFormPropertyId(ParameterFacade)
317     */
318    protected String handleGetFormPropertyId(final ParameterFacade ownerParameter)
319    {
320        return StringUtilsHelper.lowerCamelCaseName(this.getFormPropertyName(ownerParameter));
321    }
322
323    /**
324     * @param ownerParameter
325     * @return isSelectable
326     * @see JSFAttribute#isSelectable(org.andromda.metafacades.uml.FrontEndParameter)
327     */
328    protected boolean handleIsSelectable(final FrontEndParameter ownerParameter)
329    {
330        boolean selectable = false;
331        if (ownerParameter != null)
332        {
333            if (ownerParameter.isActionParameter())
334            {
335                selectable = this.isInputMultibox() || this.isInputSelect() || this.isInputRadio();
336                final ClassifierFacade type = this.getType();
337
338                if (!selectable && type != null)
339                {
340                    final String name = this.getName();
341                    final String typeName = type.getFullyQualifiedName();
342
343                    // - if the parameter is not selectable but on a targeting page it IS selectable we must
344                    //   allow the user to set the backing list too
345                    final Collection<FrontEndView> views = ownerParameter.getAction().getTargetViews();
346                    for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !selectable;)
347                    {
348                        final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters();
349                        for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator();
350                            parameterIterator.hasNext() && !selectable;)
351                        {
352                            final FrontEndParameter object = parameterIterator.next();
353                            if (object instanceof JSFParameter)
354                            {
355                                final JSFParameter parameter = (JSFParameter)object;
356                                final String parameterName = parameter.getName();
357                                final ClassifierFacade parameterType = parameter.getType();
358                                if (parameterType != null)
359                                {
360                                    final String parameterTypeName = parameterType.getFullyQualifiedName();
361                                    if (name.equals(parameterName) && typeName.equals(parameterTypeName))
362                                    {
363                                        selectable =
364                                            parameter.isInputMultibox() || parameter.isInputSelect() ||
365                                            parameter.isInputRadio();
366                                    }
367                                }
368                            }
369                        }
370                    }
371                }
372            }
373            else if (ownerParameter.isControllerOperationArgument())
374            {
375                final String name = this.getName();
376                for (final FrontEndAction action : ownerParameter.getControllerOperation().getDeferringActions())
377                {
378                    final Collection<FrontEndParameter> formFields = action.getFormFields();
379                    for (final Iterator<FrontEndParameter> fieldIterator = formFields.iterator(); fieldIterator.hasNext() && !selectable;)
380                    {
381                        final FrontEndParameter object = fieldIterator.next();
382                        if (object instanceof JSFParameter)
383                        {
384                            final JSFParameter parameter = (JSFParameter)object;
385                            if (name.equals(parameter.getName()))
386                            {
387                                selectable = parameter.isSelectable();
388                            }
389                        }
390                    }
391                }
392            }
393        }
394        return selectable;
395    }
396
397    /**
398     * @return !this.getValidatorTypes().isEmpty()
399     * @see JSFAttribute#isValidationRequired()
400     */
401    protected boolean handleIsValidationRequired()
402    {
403        return !this.getValidatorTypes().isEmpty();
404    }
405
406    /**
407     * @return validatorTypes
408     * @see JSFAttribute#getValidatorTypes()
409     */
410    protected Collection<String> handleGetValidatorTypes()
411    {
412        return JSFUtils.getValidatorTypes(
413            (ModelElementFacade)this.THIS(),
414            this.getType());
415    }
416
417    /**
418     * @param ownerParameter
419     * @return validatorVars
420     * @see JSFAttribute#getValidatorVars(JSFParameter)
421     */
422    protected Collection<List<String>> handleGetValidatorVars(JSFParameter ownerParameter)
423    {
424        return JSFUtils.getValidatorVars(
425            (ModelElementFacade)this.THIS(),
426            this.getType(),
427            ownerParameter);
428    }
429
430    /**
431     * @return JSFUtils.getValidWhen(this)
432     * @see JSFAttribute#getValidWhen()
433     */
434    protected String handleGetValidWhen()
435    {
436        return JSFUtils.getValidWhen(this);
437    }
438
439    /**
440     * @return isInputType(JSFGlobals.INPUT_TEXTAREA)
441     * @see JSFAttribute#isInputTextarea()
442     */
443    protected boolean handleIsInputTextarea()
444    {
445        return this.isInputType(JSFGlobals.INPUT_TEXTAREA);
446    }
447
448    /**
449     * @return isInputType(JSFGlobals.INPUT_SELECT)
450     * @see JSFAttribute#isInputSelect()
451     */
452    protected boolean handleIsInputSelect()
453    {
454        return this.isInputType(JSFGlobals.INPUT_SELECT);
455    }
456
457    /**
458     * @return isInputType(JSFGlobals.INPUT_PASSWORD)
459     * @see JSFAttribute#isInputSecret()
460     */
461    protected boolean handleIsInputSecret()
462    {
463        return this.isInputType(JSFGlobals.INPUT_PASSWORD);
464    }
465
466    /**
467     * @return isInputType(JSFGlobals.INPUT_HIDDEN)
468     * @see JSFAttribute#isInputHidden()
469     */
470    protected boolean handleIsInputHidden()
471    {
472        return this.isInputType(JSFGlobals.INPUT_HIDDEN);
473    }
474
475    /**
476     * @return isInputType(JSFGlobals.PLAIN_TEXT)
477     * @see JSFAttribute#isPlaintext()
478     */
479    protected boolean handleIsPlaintext()
480    {
481        return this.isInputType(JSFGlobals.PLAIN_TEXT);
482    }
483
484    /**
485     * @return isInputType(JSFGlobals.INPUT_RADIO)
486     * @see JSFAttribute#isInputRadio()
487     */
488    protected boolean handleIsInputRadio()
489    {
490        return this.isInputType(JSFGlobals.INPUT_RADIO);
491    }
492
493    /**
494     * @return isInputType(JSFGlobals.INPUT_TEXT)
495     * @see JSFAttribute#isInputText()
496     */
497    protected boolean handleIsInputText()
498    {
499        return this.isInputType(JSFGlobals.INPUT_TEXT);
500    }
501
502    /**
503     * @return isInputType(JSFGlobals.INPUT_MULTIBOX)
504     * @see JSFAttribute#isInputMultibox()
505     */
506    protected boolean handleIsInputMultibox()
507    {
508        return this.isInputType(JSFGlobals.INPUT_MULTIBOX);
509    }
510
511    /**
512     * @return inputTable
513     * @see JSFAttribute#isInputTable()
514     */
515    protected boolean handleIsInputTable()
516    {
517        return this.getInputTableIdentifierColumns().length() > 0 || this.isInputType(JSFGlobals.INPUT_TABLE);
518    }
519
520    /**
521     * @return inputCheckbox
522     * @see JSFAttribute#isInputCheckbox()
523     */
524    protected boolean handleIsInputCheckbox()
525    {
526        boolean checkbox = this.isInputType(JSFGlobals.INPUT_CHECKBOX);
527        if (!checkbox && this.getInputType().length() == 0)
528        {
529            final ClassifierFacade type = this.getType();
530            checkbox = type != null ? type.isBooleanType() : false;
531        }
532        return checkbox;
533    }
534
535    /**
536     * Gets the current value of the specified input type (or an empty string
537     * if one isn't specified).
538     *
539     * @return the input type name.
540     */
541    private String getInputType()
542    {
543        return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TYPE)).trim();
544    }
545
546    /**
547     * Indicates whether or not this parameter is of the given input type.
548     *
549     * @param inputType the name of the input type to check for.
550     * @return true/false
551     */
552    private boolean isInputType(final String inputType)
553    {
554        return inputType.equalsIgnoreCase(this.getInputType());
555    }
556
557    /**
558     * @return inputFile
559     * @see JSFAttribute#isInputFile()
560     */
561    protected boolean handleIsInputFile()
562    {
563        boolean file = false;
564        ClassifierFacade type = getType();
565        if (type != null)
566        {
567            file = type.isFileType();
568        }
569        return file;
570    }
571
572    /**
573     * Overridden to provide consistent behavior with {@link JSFParameter#isReadOnly()}.
574     *
575     * @see org.andromda.metafacades.uml.AttributeFacade#isReadOnly()
576     */
577    public boolean isReadOnly()
578    {
579        return JSFUtils.isReadOnly(this);
580    }
581
582    /**
583     * @return constructDummyArray()
584     * @see JSFAttribute#getValueListDummyValue()
585     */
586    protected String handleGetValueListDummyValue()
587    {
588        return this.constructDummyArray();
589    }
590
591    /**
592     * @param validatorType
593     * @return getValidatorArgs
594     * @see JSFAttribute#getValidatorArgs(String)
595     */
596    protected Collection handleGetValidatorArgs(final String validatorType)
597    {
598        return JSFUtils.getValidatorArgs(
599            (ModelElementFacade)this.THIS(),
600            validatorType);
601    }
602
603    /**
604     * @return isStrictDateFormat
605     * @see JSFAttribute#isStrictDateFormat()
606     */
607    protected boolean handleIsStrictDateFormat()
608    {
609        return JSFUtils.isStrictDateFormat((ModelElementFacade)this.THIS());
610    }
611
612    /**
613     * @param ownerParameter
614     * @return dateFormatter
615     * @see JSFAttribute#getDateFormatter(org.andromda.cartridges.jsf2.metafacades.JSFParameter)
616     */
617    protected String handleGetDateFormatter(final JSFParameter ownerParameter)
618    {
619        final ClassifierFacade type = this.getType();
620        return type != null && type.isDateType() ? this.getFormPropertyId(ownerParameter) + "DateFormatter" : null;
621    }
622
623    /**
624     * @param ownerParameter
625     * @return timeFormatter
626     * @see JSFAttribute#getTimeFormatter(org.andromda.cartridges.jsf2.metafacades.JSFParameter)
627     */
628    protected String handleGetTimeFormatter(final JSFParameter ownerParameter)
629    {
630        final ClassifierFacade type = this.getType();
631        return type != null && type.isTimeType() ? this.getFormPropertyId(ownerParameter) + "TimeFormatter" : null;
632    }
633
634    /**
635     * Overridden to provide quotes around string types.
636     *
637     * @see org.andromda.metafacades.uml.AttributeFacade#getDefaultValue()
638     */
639    public String getDefaultValue()
640    {
641        String defaultValue = super.getDefaultValue();
642        if (StringUtils.isNotBlank(defaultValue))
643        {
644            final ClassifierFacade type = this.getType();
645            if (type != null && type.isStringType())
646            {
647                defaultValue = "\"" + defaultValue + "\"";
648            }
649        }
650        return defaultValue;
651    }
652
653    /**
654     * @return isEqualValidator
655     * @see JSFAttribute#isEqualValidator()
656     */
657    protected boolean handleIsEqualValidator()
658    {
659        final String equal = JSFUtils.getEqual((ModelElementFacade)this.THIS());
660        return equal != null && equal.trim().length() > 0;
661    }
662
663    /**
664     * @param ownerParameter
665     * @return isBackingValueRequired
666     * @see JSFAttribute#isBackingValueRequired(org.andromda.metafacades.uml.FrontEndParameter)
667     */
668    protected boolean handleIsBackingValueRequired(final FrontEndParameter ownerParameter)
669    {
670        boolean required = false;
671        if (ownerParameter != null)
672        {
673            if (ownerParameter.isActionParameter())
674            {
675                required = this.isInputTable();
676                final ClassifierFacade type = this.getType();
677
678                if (!required && type != null)
679                {
680                    final String name = this.getName();
681                    final String typeName = type.getFullyQualifiedName();
682
683                    // - if the parameter is not selectable but on a targetting page it IS selectable we must
684                    //   allow the user to set the backing list too
685                    final Collection<FrontEndView> views = ownerParameter.getAction().getTargetViews();
686                    for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !required;)
687                    {
688                        final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters();
689                        for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator();
690                            parameterIterator.hasNext() && !required;)
691                        {
692                            final FrontEndParameter object = parameterIterator.next();
693                            if (object instanceof JSFParameter)
694                            {
695                                final JSFParameter parameter = (JSFParameter)object;
696                                final String parameterName = parameter.getName();
697                                final ClassifierFacade parameterType = parameter.getType();
698                                if (parameterType != null)
699                                {
700                                    final String parameterTypeName = parameterType.getFullyQualifiedName();
701                                    if (name.equals(parameterName) && typeName.equals(parameterTypeName))
702                                    {
703                                        required = parameter.isInputTable();
704                                    }
705                                }
706                            }
707                        }
708                    }
709                }
710            }
711            else if (ownerParameter.isControllerOperationArgument())
712            {
713                final String name = this.getName();
714                final Collection<FrontEndAction> actions = ownerParameter.getControllerOperation().getDeferringActions();
715                for (final Iterator<FrontEndAction> actionIterator = actions.iterator(); actionIterator.hasNext();)
716                {
717                    final JSFAction action = (JSFAction)actionIterator.next();
718                    final Collection<FrontEndParameter> formFields = action.getFormFields();
719                    for (final Iterator<FrontEndParameter> fieldIterator = formFields.iterator();
720                        fieldIterator.hasNext() && !required;)
721                    {
722                        final FrontEndParameter object = fieldIterator.next();
723                        if (object instanceof JSFParameter)
724                        {
725                            final JSFParameter parameter = (JSFParameter)object;
726                            if (name.equals(parameter.getName()))
727                            {
728                                required = parameter.isBackingValueRequired();
729                            }
730                        }
731                    }
732                }
733            }
734        }
735        return required;
736    }
737
738    /**
739     * @return present
740     * @see JSFAttribute#isInputTypePresent()
741     */
742    protected boolean handleIsInputTypePresent()
743    {
744        boolean present = false;
745        final ClassifierFacade type = this.getType();
746        if (type != null)
747        {
748            present =
749                (StringUtils.isNotBlank(this.getInputType()) || type.isDateType() || type.isBooleanType()) &&
750                !this.isPlaintext();
751        }
752        return present;
753    }
754
755    /**
756     * @return findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS)
757     * @see JSFAttribute#getInputTableIdentifierColumns()
758     */
759    protected String handleGetInputTableIdentifierColumns()
760    {
761        return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS)).trim();
762    }
763
764    /**
765     * @return maxlength
766     * @see JSFAttribute#getMaxLength()
767     */
768    protected String handleGetMaxLength()
769    {
770        final Collection<List<String>> vars = this.getValidatorVars(null);
771        if(vars == null)
772        {
773            return null;
774        }
775        for(final List<String> values : vars)
776        {
777            if("maxlength".equals(values.get(0)))
778            {
779                return values.get(1);
780            }
781        }
782        return null;
783    }
784}