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