View Javadoc
1   package org.andromda.cartridges.jsf;
2   
3   import java.security.MessageDigest;
4   import java.security.NoSuchAlgorithmException;
5   import java.util.ArrayList;
6   import java.util.Arrays;
7   import java.util.Collection;
8   import java.util.Date;
9   import java.util.Iterator;
10  import java.util.LinkedHashMap;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.regex.Pattern;
14  import org.andromda.cartridges.jsf.metafacades.JSFAttribute;
15  import org.andromda.cartridges.jsf.metafacades.JSFManageableEntityAttribute;
16  import org.andromda.cartridges.jsf.metafacades.JSFParameter;
17  import org.andromda.metafacades.uml.AttributeFacade;
18  import org.andromda.metafacades.uml.ClassifierFacade;
19  import org.andromda.metafacades.uml.FrontEndAction;
20  import org.andromda.metafacades.uml.FrontEndParameter;
21  import org.andromda.metafacades.uml.ModelElementFacade;
22  import org.andromda.metafacades.uml.OperationFacade;
23  import org.andromda.metafacades.uml.ParameterFacade;
24  import org.andromda.metafacades.uml.UMLMetafacadeUtils;
25  import org.andromda.utils.StringUtilsHelper;
26  import org.apache.commons.lang.ObjectUtils;
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.commons.lang.time.FastDateFormat;
29  
30  /**
31   * Utilities for use within the JSF cartridge.
32   *
33   * @author Chad Brandon
34   */
35  public class JSFUtils
36  {
37      /**
38       * Converts the argument into a web resource name, this means: all lowercase
39       * characters and words are separated with dashes.
40       *
41       * @param string any string
42       * @return the string converted to a value that would be well-suited for a
43       *         web file name
44       */
45      public static String toWebResourceName(final String string)
46      {
47          return StringUtilsHelper.separate(
48              string,
49              "-").toLowerCase();
50      }
51  
52      private static final Pattern VALIDATOR_TAGGEDVALUE_PATTERN =
53          Pattern.compile("\\w+(\\(\\w+=[^,)]*(,\\w+=[^,)]*)*\\))?");
54  
55      private static final String ANNOTATION_VALIDATOR_PREFIX = "@";
56  
57      /**
58       * Reads the validator arguments from the the given tagged value.
59       * @param validatorTaggedValue
60       * @return returns a list of String instances or an empty list
61       * @throws IllegalArgumentException when the input string does not match the required pattern
62       */
63      public static List<String> parseValidatorArgs(String validatorTaggedValue)
64      {
65          if (validatorTaggedValue == null)
66          {
67              throw new IllegalArgumentException("Validator tagged value cannot be null");
68          }
69  
70          final List<String> validatorArgs = new ArrayList<String>();
71  
72          //isn't it an annotation ?
73          if(!StringUtils.startsWith(validatorTaggedValue,ANNOTATION_VALIDATOR_PREFIX))
74          {
75  
76              // check if the input tagged value matches the required pattern
77              if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches())
78              {
79                  throw new IllegalArgumentException(
80                      "Illegal validator tagged value (this tag is used to specify custom validators " +
81                      "and might look like myValidator(myVar=myArg,myVar2=myArg2), perhaps you wanted to use " +
82                      "andromda_presentation_view_field_format?): " + validatorTaggedValue);
83              }
84  
85              // only keep what is between parentheses (if any)
86              int left = validatorTaggedValue.indexOf('(');
87              if (left > -1)
88              {
89                  final int right = validatorTaggedValue.indexOf(')');
90                  validatorTaggedValue = validatorTaggedValue.substring(
91                          left + 1,
92                          right);
93  
94                  final String[] pairs = validatorTaggedValue.split(",");
95                  for (int i = 0; i < pairs.length; i++)
96                  {
97                      final String pair = pairs[i];
98                      final int equalsIndex = pair.indexOf('=');
99  
100                     // it's possible the argument is the empty string
101                     if (equalsIndex < pair.length() - 1)
102                     {
103                         validatorArgs.add(pair.substring(equalsIndex + 1));
104                     }
105                     else
106                     {
107                         validatorArgs.add("");
108                     }
109                 }
110             }
111         }
112         return validatorArgs;
113     }
114 
115     /**
116      * Reads the validator variable names from the the given tagged value.
117      * @param validatorTaggedValue
118      * @return never null, returns a list of String instances
119      * @throws IllegalArgumentException when the input string does not match the required pattern
120      */
121     public static List<String> parseValidatorVars(String validatorTaggedValue)
122     {
123         if (validatorTaggedValue == null)
124         {
125             throw new IllegalArgumentException("Validator tagged value cannot be null");
126         }
127 
128         final List<String> validatorVars = new ArrayList<String>();
129 
130         //isn't it an annotation ?
131         if(!StringUtils.startsWith(validatorTaggedValue,ANNOTATION_VALIDATOR_PREFIX))
132         {
133 
134             // check if the input tagged value matches the required pattern
135             if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches())
136             {
137                 throw new IllegalArgumentException("Illegal validator tagged value: " + validatorTaggedValue);
138             }
139 
140             // only keep what is between parentheses (if any)
141             int left = validatorTaggedValue.indexOf('(');
142             if (left > -1)
143             {
144                 int right = validatorTaggedValue.indexOf(')');
145                 validatorTaggedValue = validatorTaggedValue.substring(
146                         left + 1,
147                         right);
148 
149                 final String[] pairs = validatorTaggedValue.split(",");
150                 for (int i = 0; i < pairs.length; i++)
151                 {
152                     final String pair = pairs[i];
153                     final int equalsIndex = pair.indexOf('=');
154                     validatorVars.add(pair.substring(
155                             0,
156                             equalsIndex));
157                 }
158             }
159         }
160         return validatorVars;
161     }
162 
163     /**
164      * Parses the validator name for a tagged value.
165      * @param validatorTaggedValue
166      * @return validatorTaggedValue
167      * @throws IllegalArgumentException when the input string does not match the required pattern
168      */
169     public static String parseValidatorName(final String validatorTaggedValue)
170     {
171         if (validatorTaggedValue == null)
172         {
173             throw new IllegalArgumentException("Validator tagged value cannot be null");
174         }
175 
176         //isn't it an annotation ?
177         if(StringUtils.startsWith(validatorTaggedValue, ANNOTATION_VALIDATOR_PREFIX))
178         {
179             return validatorTaggedValue;
180         }
181 
182         // check if the input tagged value matches the required pattern
183         if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches())
184         {
185             throw new IllegalArgumentException("Illegal validator tagged value: " + validatorTaggedValue);
186         }
187 
188         final int leftParen = validatorTaggedValue.indexOf('(');
189         return (leftParen == -1) ? validatorTaggedValue : validatorTaggedValue.substring(
190             0,
191             leftParen);
192     }
193 
194     /**
195      * Constructs a string representing an array initialization in Java.
196      *
197      * @param name the name to give the array.
198      * @param count the number of items to give the array.
199      * @return A String representing Java code for the initialization of an array.
200      */
201     public static String constructDummyArrayDeclaration(
202         final String name,
203         final int count)
204     {
205         final StringBuilder array = new StringBuilder("new Object[] {");
206         for (int ctr = 1; ctr <= count; ctr++)
207         {
208             array.append("\"" + name + "-" + ctr + "\"");
209             if (ctr != count)
210             {
211                 array.append(", ");
212             }
213         }
214         array.append("}");
215         return array.toString();
216     }
217 
218     /**
219      * @param format
220      * @return this field's date format
221      */
222     public static String getDateFormat(String format)
223     {
224         format = StringUtils.trimToEmpty(format);
225         return format.endsWith(STRICT) ? getToken(format, 1, 2) : getToken(format, 0, 1);
226     }
227 
228     private static String defaultDateFormat = "MM/dd/yyyy HH:mm:ssZ";
229     private static FastDateFormat df = FastDateFormat.getInstance(defaultDateFormat);
230 
231     /**
232      * Returns the current Date in the specified format.
233      *
234      * @param format The format for the output date
235      * @return the current date in the specified format.
236      */
237     public static String getDate(String format)
238     {
239         if (df == null || !format.equals(df.getPattern()))
240         {
241             df = FastDateFormat.getInstance(format);
242         }
243         return df.format(new Date());
244     }
245 
246     /**
247      * Returns the current Date
248      *
249      * @return the current date in the default format.
250      */
251     public static String getDate()
252     {
253         return getDate(defaultDateFormat);
254     }
255 
256     private static final String STRICT = "strict";
257 
258     /**
259      * @param format
260      * @return <code>true</code> if this field's value needs to conform to a
261      * strict date format, <code>false</code> otherwise
262      */
263     public static boolean isStrictDateFormat(String format)
264     {
265         return strictDateTimeFormat ? strictDateTimeFormat : STRICT.equalsIgnoreCase(getToken(
266                 format,
267                 0,
268                 2));
269     }
270 
271     /**
272      * Indicates if the given <code>format</code> is an email format.
273      * @param format
274      * @return <code>true</code> if this field is to be formatted as an email
275      * address, <code>false</code> otherwise
276      */
277     public static boolean isEmailFormat(String format)
278     {
279         return "email".equalsIgnoreCase(JSFUtils.getToken(
280                 format,
281                 0,
282                 2));
283     }
284 
285     /**
286      * Indicates if the given <code>format</code> is an equal format.
287      * @param format
288      * @return <code>true</code> if this field is to be formatted as an
289      * email address, <code>false</code> otherwise
290      */
291     public static boolean isEqualFormat(String format)
292     {
293         return "equal".equalsIgnoreCase(JSFUtils.getToken(format, 0, 2));
294     }
295 
296     /**
297      * Indicates if the given <code>format</code> is a credit card format.
298      * @param format
299      * @return <code>true</code> if this field is to be formatted as a credit card, <code>false</code> otherwise
300      */
301     public static boolean isCreditCardFormat(final String format)
302     {
303         return "creditcard".equalsIgnoreCase(JSFUtils.getToken(format, 0, 2));
304     }
305 
306     /**
307      * Indicates if the given <code>format</code> is a pattern format.
308      * @param format
309      * @return <code>true</code> if this field's value needs to respect a certain pattern, <code>false</code> otherwise
310      */
311     public static boolean isPatternFormat(final String format)
312     {
313         return "pattern".equalsIgnoreCase(JSFUtils.getToken(format, 0, 2));
314     }
315 
316     /**
317      * Indicates if the given <code>format</code> is a minlength format.
318      * @param format
319      * @return <code>true</code> if this field's value needs to consist of at least a certain
320      *         number of characters, <code>false</code> otherwise
321      */
322     public static boolean isMinLengthFormat(final String format)
323     {
324         return "minlength".equalsIgnoreCase(JSFUtils.getToken(
325                 format,
326                 0,
327                 2));
328     }
329 
330     /**
331      * Indicates if the given <code>format</code> is a maxlength format.
332      * @param format
333      * @return <code>true</code> if this field's value needs to consist of at maximum a certain
334      *         number of characters, <code>false</code> otherwise
335      */
336     public static boolean isMaxLengthFormat(String format)
337     {
338         return "maxlength".equalsIgnoreCase(JSFUtils.getToken(
339                 format,
340                 0,
341                 2));
342     }
343 
344     /**
345      * @param string
346      * @param index
347      * @param limit
348      * @return the i-th space delimited token read from the argument String, where i does not exceed the specified limit
349      */
350     public static String getToken(
351         String string,
352         int index,
353         int limit)
354     {
355         String token = null;
356         if (string != null && string.length() > 0)
357         {
358             final String[] tokens = string.split(
359                     "[\\s]+",
360                     limit);
361             token = index >= tokens.length ? null : tokens[index];
362         }
363         return token;
364     }
365 
366     /**
367      * Retrieves the input format (if one is defined), for the given
368      * <code>element</code>.
369      * @param element the model element for which to retrieve the input format.
370      * @return the input format.
371      */
372     public static String getInputFormat(final ModelElementFacade element)
373     {
374         final Object value = element.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_FORMAT);
375         final String format = value == null ? null : String.valueOf(value);
376         return format == null ? null : format.trim();
377     }
378 
379     /**
380      * Indicates if the given <code>format</code> is a range format.
381      * @param format
382      * @return <code>true</code> if this field's value needs to be in a specific range, <code>false</code> otherwise
383      */
384     public static boolean isRangeFormat(final String format)
385     {
386         return "range".equalsIgnoreCase(JSFUtils.getToken(
387                 format,
388                 0,
389                 2));
390     }
391 
392     /**
393      * @param type
394      * @return <code>true</code> if the type of this field is a byte, <code>false</code> otherwise
395      */
396     public static boolean isByte(final ClassifierFacade type)
397     {
398         return isType(
399             type,
400             JSFProfile.BYTE_TYPE_NAME);
401     }
402 
403     /**
404      * @param type
405      * @return <code>true</code> if the type of this field is a short, <code>false</code> otherwise
406      */
407     public static boolean isShort(final ClassifierFacade type)
408     {
409         return isType(
410             type,
411             JSFProfile.SHORT_TYPE_NAME);
412     }
413 
414     /**
415      * @param type
416      * @return <code>true</code> if the type of this field is an integer, <code>false</code> otherwise
417      */
418     public static boolean isInteger(final ClassifierFacade type)
419     {
420         return isType(
421             type,
422             JSFProfile.INTEGER_TYPE_NAME);
423     }
424 
425     /**
426      * @param type
427      * @return <code>true</code> if the type of this field is a long integer, <code>false</code> otherwise
428      */
429     public static boolean isLong(final ClassifierFacade type)
430     {
431         return isType(
432             type,
433             JSFProfile.LONG_TYPE_NAME);
434     }
435 
436     /**
437      * @param type
438      * @return <code>true</code> if the type of this field is a floating point, <code>false</code> otherwise
439      */
440     public static boolean isFloat(final ClassifierFacade type)
441     {
442         return isType(
443             type,
444             JSFProfile.FLOAT_TYPE_NAME);
445     }
446 
447     /**
448      * @param type
449      * @return <code>true</code> if the type of this field is a double precision floating point,
450      * <code>false</code> otherwise
451      */
452     public static boolean isDouble(final ClassifierFacade type)
453     {
454         return isType(
455             type,
456             JSFProfile.DOUBLE_TYPE_NAME);
457     }
458 
459     /**
460      * @param type
461      * @return <code>true</code> if the type of this field is a date, <code>false</code> otherwise
462      */
463     public static boolean isDate(final ClassifierFacade type)
464     {
465         return type != null && type.isDateType();
466     }
467 
468     /**
469      * @param type
470      * @return <code>true</code> if the type of this field is a time, <code>false</code> otherwise
471      */
472     public static boolean isTime(final ClassifierFacade type)
473     {
474         return isType(
475             type,
476             JSFProfile.TIME_TYPE_NAME);
477     }
478 
479     /**
480      * @param type
481      * @return <code>true</code> if the type of this field is a URL, <code>false</code> otherwise
482      */
483     public static boolean isUrl(final ClassifierFacade type)
484     {
485         return isType(
486             type,
487             JSFProfile.URL_TYPE_NAME);
488     }
489 
490     private static boolean isType(final ClassifierFacade type, String typeName)
491     {
492         boolean isType = UMLMetafacadeUtils.isType(
493             type,
494             typeName);
495         if (!isType)
496         {
497             // - handle abstract types that are mapped to java types
498             if (type.getLanguageMappings() != null)
499             {
500                 final String javaTypeName = type.getLanguageMappings()
501                     .getTo(type.getFullyQualifiedName(true));
502                 if (javaTypeName != null)
503                 {
504                     isType = javaTypeName.replaceAll(".*\\.", "").equalsIgnoreCase(
505                         type.getLanguageMappings().getTo(typeName));
506                 }
507             }
508         }
509         return isType;
510     }
511 
512     /**
513      * @param type
514      * @return <code>true</code> if the type of this field is a String,
515      * <code>false</code> otherwise
516      */
517     public static boolean isString(final ClassifierFacade type)
518     {
519         return type != null && type.isStringType();
520     }
521 
522     /**
523      * Indicates if the given element is read-only or not.
524      *
525      * @param element the element to check.
526      * @return true/false
527      */
528     public static boolean isReadOnly(final ModelElementFacade element)
529     {
530         boolean readOnly = false;
531         if (element != null)
532         {
533             final Object value = element.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_READONLY);
534             readOnly = Boolean.valueOf(ObjectUtils.toString(value)).booleanValue();
535         }
536         return readOnly;
537     }
538 
539     /**
540      * Retrieves the "equal" value from the given element (if one is present).
541      *
542      * @param element the element from which to retrieve the equal value.
543      * @return the "equal" value.
544      */
545     public static String getEqual(final ModelElementFacade element)
546     {
547         String equal = null;
548         if (element != null)
549         {
550             final Object value = element.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_EQUAL);
551             equal = value == null ? null : value.toString();
552         }
553         return equal;
554     }
555 
556     /**
557      * Retrieves the "equal" value from the given element (if one is present).
558      *
559      * @param element the element from which to retrieve the equal value.
560      * @param ownerParameter the optional owner parameter (specified if the element is an attribute).
561      * @return the "equal" value.
562      */
563     public static String getEqual(final ModelElementFacade element, final ParameterFacade ownerParameter)
564     {
565         String equal = null;
566         if (element != null)
567         {
568             final Object value = element.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_EQUAL);
569             equal = value == null ? null : value.toString();
570             if (StringUtils.isNotBlank(equal) && ownerParameter != null)
571             {
572                 equal = ownerParameter.getName() + StringUtilsHelper.upperCamelCaseName(equal);
573             }
574         }
575         return equal;
576     }
577 
578     /**
579      * Retrieves the "validwhen" value from the given element (if one is present).
580      *
581      * @param element the element from which to retrieve the validwhen value.
582      * @return the "validwhen" value.
583      */
584     public static String getValidWhen(final ModelElementFacade element)
585     {
586         String validWhen = null;
587         if (element != null)
588         {
589             final Object value = element.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_VALIDWHEN);
590             validWhen = value == null ? null : '(' + value.toString() + ')';
591         }
592         return validWhen;
593     }
594 
595     /**
596      * @param format
597      * @return the lower limit for this field's value's range
598      */
599     public static String getRangeStart(final String format)
600     {
601         return JSFUtils.getToken(
602             format,
603             1,
604             3);
605     }
606 
607     /**
608      * @param format
609      * @return the upper limit for this field's value's range
610      */
611     public static String getRangeEnd(final String format)
612     {
613         return JSFUtils.getToken(
614             format,
615             2,
616             3);
617     }
618 
619     /**
620      * @param format
621      * @return the minimum number of characters this field's value must consist of
622      */
623     public static String getMinLengthValue(final String format)
624     {
625         return JSFUtils.getToken(
626             format,
627             1,
628             2);
629     }
630 
631     /**
632      * @param format
633      * @return the maximum number of characters this field's value must consist of
634      */
635     public static String getMaxLengthValue(final String format)
636     {
637         return JSFUtils.getToken(
638             format,
639             1,
640             2);
641     }
642 
643     /**
644      * @param format
645      * @return the pattern this field's value must respect
646      */
647     public static String getPatternValue(final String format)
648     {
649         return '^' + JSFUtils.getToken(
650             format,
651             1,
652             2) + '$';
653     }
654 
655     //validator strings
656     /** "required" */
657     public static final String VT_REQUIRED="required";
658     /** "url" */
659     public static final String VT_URL="url";
660     /** "intRange" */
661     public static final String VT_INT_RANGE="intRange";
662     /** "floatRange" */
663     public static final String VT_FLOAT_RANGE="floatRange";
664     /** "doubleRange" */
665     public static final String VT_DOUBLE_RANGE="doubleRange";
666     /** "email" */
667     public static final String VT_EMAIL="email";
668     /** "creditCard" */
669     public static final String VT_CREDIT_CARD="creditCard";
670     /** "minlength" */
671     public static final String VT_MIN_LENGTH="minlength";
672     /** "maxlength" */
673     public static final String VT_MAX_LENGTH="maxlength";
674     /** "mask" */
675     public static final String VT_MASK="mask";
676     /** "validwhen" */
677     public static final String VT_VALID_WHEN="validwhen";
678     /** "equal" */
679     public static final String VT_EQUAL="equal";
680 
681     /**
682      * Retrieves the validator types as a collection from the given
683      * <code>element</code> (if any can be retrieved).
684      *
685      * @param element the element from which to retrieve the types.
686      * @param type the type of the element.
687      * @return the collection of validator types.
688      */
689     public static Collection<String> getValidatorTypes(
690         final ModelElementFacade element,
691         final ClassifierFacade type)
692     {
693         final Collection<String> validatorTypesList = new ArrayList<String>();
694         if (element != null && type != null)
695         {
696             final String format = JSFUtils.getInputFormat(element);
697             final boolean isRangeFormat = format != null && isRangeFormat(format);
698             if (element instanceof AttributeFacade)
699             {
700                 if (((AttributeFacade)element).isRequired())
701                 {
702                     validatorTypesList.add(VT_REQUIRED);
703                 }
704             }
705             else if (element instanceof JSFParameter)
706             {
707                 if (((JSFParameter)element).isRequired())
708                 {
709                     validatorTypesList.add(VT_REQUIRED);
710                 }
711             }
712             if (JSFUtils.isByte(type))
713             {
714                 validatorTypesList.add("byte");
715             }
716             else if (JSFUtils.isShort(type))
717             {
718                 validatorTypesList.add("short");
719             }
720             else if (JSFUtils.isInteger(type))
721             {
722                 validatorTypesList.add("integer");
723             }
724             else if (JSFUtils.isLong(type))
725             {
726                 validatorTypesList.add("long");
727             }
728             else if (JSFUtils.isFloat(type))
729             {
730                 validatorTypesList.add("float");
731             }
732             else if (JSFUtils.isDouble(type))
733             {
734                 validatorTypesList.add("double");
735             }
736             else if (JSFUtils.isDate(type))
737             {
738                 validatorTypesList.add("date");
739             }
740             else if (JSFUtils.isTime(type))
741             {
742                 validatorTypesList.add("time");
743             }
744             else if (JSFUtils.isUrl(type))
745             {
746                 validatorTypesList.add(VT_URL);
747             }
748 
749             if (isRangeFormat)
750             {
751                 if (JSFUtils.isInteger(type) || JSFUtils.isShort(type) || JSFUtils.isLong(type))
752                 {
753                     validatorTypesList.add(VT_INT_RANGE);
754                 }
755                 if (JSFUtils.isFloat(type))
756                 {
757                     validatorTypesList.add(VT_FLOAT_RANGE);
758                 }
759                 if (JSFUtils.isDouble(type))
760                 {
761                     validatorTypesList.add(VT_DOUBLE_RANGE);
762                 }
763             }
764 
765             if (format != null)
766             {
767                 if (JSFUtils.isString(type) && JSFUtils.isEmailFormat(format))
768                 {
769                     validatorTypesList.add(VT_EMAIL);
770                 }
771                 else if (JSFUtils.isString(type) && JSFUtils.isCreditCardFormat(format))
772                 {
773                     validatorTypesList.add(VT_CREDIT_CARD);
774                 }
775                 else
776                 {
777                     Collection formats = element.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT);
778                     for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
779                     {
780                         String additionalFormat = String.valueOf(formatIterator.next());
781                         if (JSFUtils.isMinLengthFormat(additionalFormat))
782                         {
783                             validatorTypesList.add(VT_MIN_LENGTH);
784                         }
785                         else if (JSFUtils.isMaxLengthFormat(additionalFormat))
786                         {
787                             validatorTypesList.add(VT_MAX_LENGTH);
788                         }
789                         else if (JSFUtils.isPatternFormat(additionalFormat))
790                         {
791                             validatorTypesList.add(VT_MASK);
792                         }
793                     }
794                 }
795             }
796             if (JSFUtils.getValidWhen(element) != null)
797             {
798                 validatorTypesList.add(VT_VALID_WHEN);
799             }
800             if (JSFUtils.getEqual(element) != null)
801             {
802                 validatorTypesList.add(VT_EQUAL);
803             }
804 
805             // - custom (paramterized) validators are allowed here
806             final Collection taggedValues = element.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_VALIDATORS);
807             for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();)
808             {
809                 String validator = String.valueOf(iterator.next());
810                 validatorTypesList.add(JSFUtils.parseValidatorName(validator));
811             }
812         }
813         return validatorTypesList;
814     }
815 
816     /**
817      * Gets the validator variables for the given <code>element</code> (if they can
818      * be retrieved).
819      *
820      * @param element the element from which to retrieve the variables
821      * @param type the type of the element.
822      * @param ownerParameter the optional owner parameter (if the element is an attribute for example).
823      * @return the collection of validator variables.
824      */
825     public static Collection<List<String>> getValidatorVars(
826         final ModelElementFacade element,
827         final ClassifierFacade type,
828         final ParameterFacade ownerParameter)
829     {
830         final Map<String, List<String>> vars = new LinkedHashMap<String, List<String>>();
831         if (element != null && type != null)
832         {
833             final String format = JSFUtils.getInputFormat(element);
834             if (format != null)
835             {
836                 final boolean isRangeFormat = JSFUtils.isRangeFormat(format);
837 
838                 if (isRangeFormat)
839                 {
840                     final String min = "min";
841                     final String max = "max";
842                     vars.put(
843                         min,
844                         Arrays.asList(min, JSFUtils.getRangeStart(format)));
845                     vars.put(
846                         max,
847                         Arrays.asList(max, JSFUtils.getRangeEnd(format)));
848                 }
849                 else
850                 {
851                     final Collection formats = element.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT);
852                     for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
853                     {
854                         final String additionalFormat = String.valueOf(formatIterator.next());
855                         final String minlength = "minlength";
856                         final String maxlength = "maxlength";
857                         final String mask = "mask";
858                         if (JSFUtils.isMinLengthFormat(additionalFormat))
859                         {
860                             vars.put(
861                                 minlength,
862                                 Arrays.asList(minlength, JSFUtils.getMinLengthValue(additionalFormat)));
863                         }
864                         else if (JSFUtils.isMaxLengthFormat(additionalFormat))
865                         {
866                             vars.put(
867                                 maxlength,
868                                 Arrays.asList(maxlength, JSFUtils.getMaxLengthValue(additionalFormat)));
869                         }
870                         else if (JSFUtils.isPatternFormat(additionalFormat))
871                         {
872                             vars.put(
873                                 mask,
874                                 Arrays.asList(mask, JSFUtils.getPatternValue(additionalFormat)));
875                         }
876                     }
877                 }
878             }
879             String inputFormat;
880             if (element instanceof JSFAttribute)
881             {
882                 inputFormat = ((JSFAttribute)element).getFormat();
883             }
884             else if (element instanceof JSFParameter)
885             {
886                 inputFormat = ((JSFParameter)element).getFormat();
887             }
888             else if (element instanceof JSFManageableEntityAttribute)
889             {
890                 inputFormat = ((JSFManageableEntityAttribute)element).getFormat();
891             }
892             else
893             {
894                 throw new RuntimeException("'element' is an invalid type, it must be either an instance of '" +
895                     JSFAttribute.class.getName() + "' or '" + JSFParameter.class.getName() + "'");
896             }
897             if (JSFUtils.isDate(type))
898             {
899                 final String datePatternStrict = "datePatternStrict";
900                 if (format != null && JSFUtils.isStrictDateFormat(format))
901                 {
902                     vars.put(
903                         datePatternStrict,
904                         Arrays.asList(datePatternStrict, inputFormat));
905                 }
906                 else
907                 {
908                     final String datePattern = "datePattern";
909                     vars.put(
910                         datePattern,
911                         Arrays.asList(datePattern, inputFormat));
912                 }
913             }
914             if (JSFUtils.isTime(type))
915             {
916                 final String timePattern = "timePattern";
917                 vars.put(
918                     timePattern,
919                     Arrays.asList(timePattern, inputFormat));
920             }
921 
922             final String validWhen = JSFUtils.getValidWhen(element);
923             if (validWhen != null)
924             {
925                 final String test = "test";
926                 vars.put(
927                     test,
928                     Arrays.asList(test, validWhen));
929             }
930 
931             final String equal = JSFUtils.getEqual(element, ownerParameter);
932             if (equal != null)
933             {
934                 final String fieldName = "fieldName";
935                 vars.put(
936                     fieldName,
937                     Arrays.asList(fieldName, equal));
938             }
939 
940             // - custom (parameterized) validators are allowed here
941             //   in this case we will reuse the validator arg values
942             final Collection taggedValues = element.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_VALIDATORS);
943             for (final Object value : taggedValues)
944             {
945                 final String validator = String.valueOf(value);
946 
947                 // - guaranteed to be of the same length
948                 final List<String> validatorVars = JSFUtils.parseValidatorVars(validator);
949                 final List<String> validatorArgs = JSFUtils.parseValidatorArgs(validator);
950 
951                 for (int ctr = 0; ctr < validatorVars.size(); ctr++)
952                 {
953                     vars.put(validatorVars.get(ctr),
954                         Arrays.asList(validatorVars.get(ctr), validatorArgs.get(ctr)));
955                 }
956             }
957         }
958         return vars.values();
959     }
960 
961     /**
962      * Gets the validator args for the <code>element</code> and the given <code>validatorType</code>.
963      *
964      * @param element the element for which to retrieve the arguments.
965      * @param validatorType the validator type name.
966      * @return the validator args as a collection.
967      */
968     public static java.util.Collection getValidatorArgs(
969         final ModelElementFacade element,
970         final String validatorType)
971     {
972         final Collection<Object> args = new ArrayList<Object>();
973         if ("intRange".equals(validatorType) || "floatRange".equals(validatorType) ||
974             "doubleRange".equals(validatorType))
975         {
976             args.add("${var:min}");
977             args.add("${var:max}");
978         }
979         else if ("minlength".equals(validatorType))
980         {
981             args.add("${var:minlength}");
982         }
983         else if ("maxlength".equals(validatorType))
984         {
985             args.add("${var:maxlength}");
986         }
987         else if ("date".equals(validatorType))
988         {
989             final String validatorFormat = JSFUtils.getInputFormat(element);
990             if (JSFUtils.isStrictDateFormat(validatorFormat))
991             {
992                 args.add("${var:datePatternStrict}");
993             }
994             else
995             {
996                 args.add("${var:datePattern}");
997             }
998         }
999         else if ("time".equals(validatorType))
1000         {
1001             args.add("${var:timePattern}");
1002         }
1003         else if ("equal".equals(validatorType))
1004         {
1005             ModelElementFacade equalParameter = null;
1006             final String equal = JSFUtils.getEqual(element);
1007             if (element instanceof ParameterFacade)
1008             {
1009                 final FrontEndParameter parameter = (FrontEndParameter)element;
1010                 final OperationFacade operation = parameter.getOperation();
1011                 if (operation != null)
1012                 {
1013                     equalParameter = operation.findParameter(equal);
1014                 }
1015                 if (equalParameter == null)
1016                 {
1017                     final FrontEndAction action = parameter.getAction();
1018                     if (action != null)
1019                     {
1020                         equalParameter = action.findParameter(equal);
1021                     }
1022                 }
1023             }
1024             else if (element instanceof AttributeFacade)
1025             {
1026                 final AttributeFacade attribute = (AttributeFacade)element;
1027                 final ClassifierFacade owner = attribute.getOwner();
1028                 if (owner != null)
1029                 {
1030                     equalParameter = owner.findAttribute(equal);
1031                 }
1032             }
1033             args.add(equalParameter);
1034             args.add("${var:fieldName}");
1035         }
1036 
1037         // custom (paramterized) validators are allowed here
1038         final Collection taggedValues = element.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_VALIDATORS);
1039         for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();)
1040         {
1041             final String validator = String.valueOf(iterator.next());
1042             if (validatorType.equals(JSFUtils.parseValidatorName(validator)))
1043             {
1044                 args.addAll(JSFUtils.parseValidatorArgs(validator));
1045             }
1046         }
1047         return args;
1048     }
1049 
1050     /**
1051      * Whether or not date patterns should be treated as strict.
1052      */
1053     private static boolean strictDateTimeFormat;
1054 
1055     /**
1056      * Sets whether or not the date patterns should be treated as strict.
1057      *
1058      * @param strictDateTimeFormat
1059      */
1060     public void setStrictDateTimeFormat(final boolean strictDateTimeFormat)
1061     {
1062         JSFUtils.strictDateTimeFormat = strictDateTimeFormat;
1063     }
1064 
1065     /**
1066      * Indicates whether or not the format for this element is a strict date
1067      * format.
1068      * @param element
1069      * @return true/false
1070      */
1071     public static boolean isStrictDateFormat(final ModelElementFacade element)
1072     {
1073         final String format = JSFUtils.getInputFormat(element);
1074         return JSFUtils.isStrictDateFormat(format);
1075     }
1076 
1077     /**
1078      * Gets the format string for the given <code>element</code>.
1079      *
1080      * @param element the element for which to retrieve the format.
1081      * @param type the type of the element.
1082      * @param defaultDateFormat
1083      * @param defaultTimeFormat
1084      * @return the format string (if one is present otherwise null).
1085      */
1086     public static String getFormat(
1087         final ModelElementFacade element,
1088         final ClassifierFacade type,
1089         final String defaultDateFormat,
1090         final String defaultTimeFormat)
1091     {
1092         String format = null;
1093         if (element != null && type != null)
1094         {
1095             format = JSFUtils.getInputFormat(element);
1096             if (format == null)
1097             {
1098                 if(type.isDateType() && type.isTimeType())
1099                 {
1100                     format = defaultDateFormat+" "+defaultTimeFormat;
1101                 }
1102                 else if (type.isTimeType())
1103                 {
1104                     format = defaultTimeFormat;
1105                 }
1106                 else if (type.isDateType())
1107                 {
1108                     format = defaultDateFormat;
1109                 }
1110             }
1111             else if (type.isDateType())
1112             {
1113                 format = JSFUtils.getDateFormat(format);
1114             }
1115         }
1116         return format;
1117     }
1118 
1119     /**
1120      * The XHTML extension.
1121      */
1122     private static final String EXTENSION_XHTML = "xhtml";
1123 
1124     /**
1125      * Gets the extension for the view type.
1126      *
1127      * @return the view type extension.
1128      */
1129     public String getViewExtension()
1130     {
1131         return EXTENSION_XHTML;
1132     }
1133 
1134     private String portletContainer;
1135 
1136     /**
1137      * @param portletContainer
1138      */
1139     public void setPortletContainer(String portletContainer)
1140     {
1141         this.portletContainer = portletContainer;
1142     }
1143 
1144     private boolean isPortlet()
1145     {
1146         return StringUtils.isNotBlank(this.portletContainer);
1147     }
1148 
1149     /**
1150      * @return className
1151      */
1152     public String getRequestClassName()
1153     {
1154         final String className;
1155         if (this.isPortlet())
1156         {
1157             className = "javax.portlet.PortletRequest";
1158         }
1159         else
1160         {
1161             className = "javax.servlet.http.HttpServletRequest";
1162         }
1163         return className;
1164     }
1165 
1166     /**
1167      * @return className
1168      */
1169     public String getResponseClassName()
1170     {
1171         final String className;
1172         if (this.isPortlet())
1173         {
1174             className = "javax.portlet.PortletResponse";
1175         }
1176         else
1177         {
1178             className = "javax.servlet.http.HttpServletResponse";
1179         }
1180         return className;
1181     }
1182 
1183     /**
1184      * @return className
1185      */
1186     public String getSessionClassName()
1187     {
1188         final String className;
1189         if (this.isPortlet())
1190         {
1191             className = "javax.portlet.PortletSession";
1192         }
1193         else
1194         {
1195             className = "javax.servlet.http.HttpSession";
1196         }
1197         return className;
1198     }
1199 
1200     /**
1201      * @param buffer
1202      * @return the calculated SerialVersionUID
1203      */
1204     public static String calcSerialVersionUID(StringBuilder buffer)
1205     {
1206         final String signature = buffer.toString();
1207         String serialVersionUID = String.valueOf(0L);
1208         try
1209         {
1210             MessageDigest md = MessageDigest.getInstance("SHA");
1211             byte[] hashBytes = md.digest(signature.getBytes());
1212 
1213             long hash = 0;
1214             for (int ctr = Math.min(
1215                         hashBytes.length,
1216                         8) - 1; ctr >= 0; ctr--)
1217             {
1218                 hash = (hash << 8) | (hashBytes[ctr] & 0xFF);
1219             }
1220             serialVersionUID = String.valueOf(hash);
1221         }
1222         catch (final NoSuchAlgorithmException exception)
1223         {
1224             throw new RuntimeException("Error performing JSFAction.getFormSerialVersionUID",exception);
1225         }
1226 
1227         return serialVersionUID;
1228     }
1229 
1230     /**
1231      * @param string
1232      * @return Integer.valueOf(string) * 6000
1233      */
1234     public int calculateIcefacesTimeout(String string)
1235     {
1236         return string != null ? Integer.valueOf(string) * 6000 : 0;
1237     }
1238 }