001    package hirondelle.web4jtools.util;
002    
003    import hirondelle.web4j.util.Util;
004    import hirondelle.web4jtools.codegenerator.codes.ControlStyle;
005    import hirondelle.web4jtools.codegenerator.codes.FieldType;
006    import hirondelle.web4jtools.codegenerator.field.Field;
007    import hirondelle.web4j.util.Consts;
008    
009    /**
010    * Utility functions called from JSPs, using JSTL functions.
011    * 
012    * <P>Most of these functions are related to code generation. If the formatting provided by 
013    * this class is not adequate for your needs, you will need to change its implementation.
014    * 
015    * <P>These items are referenced in <tt>web4j.tld</tt>. 
016    * Since these functions are mostly used in pages served as plain text, it is appropriate that they 
017    * return <tt>String</tt> instead of <tt>SafeText</tt>.
018    * 
019    * <P>The text passed as incoming argument to these methods should be in a 
020    * 'natural text' style, as in <tt>'Jet Engine'</tt>, and not formatted in any 
021    * special way (such as <tt>'JetEngine'</tt> or <tt>'JET_ENGINE'</tt>).
022    */
023    public final class Functions {
024    
025      /**
026      * Format as a Java constant : <tt>LIKE_THIS</tt>.
027      * 
028      * <P>Any spaces are replaced with an underscore, and the text is converted to upper case.
029      */
030      public static String asConstant(String aFeatureName){
031        String result = aFeatureName.replace(SPACE, UNDERSCORE);
032        return result.toUpperCase();
033      }
034    
035      /**
036      * Format as a Java class name identifier : <tt>LikeThis</tt>.
037      * 
038      * <P>Any spaces are removed. 
039      */
040      public static String asType(String aText){
041        return Util.withNoSpaces(aText);
042      }
043      
044      /** Format as an argument to a method or a constructor:  <tt>aLikeThis</tt>. */
045      public static String asArgument(String aFieldName){
046        return "a" + asType(aFieldName);
047      }
048      
049      /** Format as an object field reference: <tt>fLikeThis</tt>. */
050      public static String asField(String aFieldName){
051        return "f" + asType(aFieldName);
052      }
053      
054      /** Format as a table or column name in an SQL statement: <tt>LikeThis</tt>. */
055      public static String asDbIdentifier(String aFieldName){
056        //some might prefer this as upper case.
057        return asType(aFieldName);
058      }
059      
060      /** Format as a JSP Expression Language reference to an object or a property: <tt>likeThis</tt>.  */
061      public static String asELIdentifier(String aFieldName) {
062        return firstLetterLowerCase(asType(aFieldName));
063      }
064      
065      /** Format as a local object in the body of a method: <tt>likeThis</tt>.  */
066      public static String asLocal(String aName){
067        return Util.withNoSpaces(firstLetterLowerCase(aName));
068      }
069      
070      /** Present a field as a complete HTML form control.   */
071      public static String asControl(Field aField){
072        String result = Consts.EMPTY_STRING;
073        String name = asType(aField.getName());
074        String type = aField.getControlStyle().getControlName();
075        ControlStyle style = aField.getControlStyle();
076        if ( ControlStyle.Text == style || 
077             ControlStyle.Hidden == style || 
078             ControlStyle.Password == style
079        ) {
080          result = "<input type='" + type + "' name='" + name + "'>";
081        }
082        else if ( ControlStyle.Checkbox == style ) {
083          result = "<input type='" + type+ "' name='" + name + "' value='true'>";
084        }
085        else if ( ControlStyle.Textarea == style ){
086          result = "<textarea name='" + name + "'></textarea>";
087        }
088        else if (ControlStyle.Radio == style ) {
089          result = "<c:forEach var='item' items='${" + aField.getCodeTable() + "}'><input name='" + name + "' type='radio' value='${item}'> ${item} </c:forEach>";
090        }
091        else if ( ControlStyle.Select == style ){
092          result = "<select name='" + name +  "'> <option> </option> <c:forEach var='item' items='${" + aField.getCodeTable() + "}'><option value='${item}'>${item}</option></c:forEach></select>";
093        }
094        return result;
095      }
096      
097      /** 
098      * Generate text snippet used for performing validations with the <tt>Check</tt> class.
099      * 
100      * An example return value : 
101      * <PRE>'Check.range(1, 100), Check.isRegex()'</PRE>  
102      */
103      public static String checks(Field aField) {
104        StringBuilder result = new StringBuilder();
105        //range, min, max
106        if( aField.getMinimum() != null && aField.getMaximum() != null ) {
107          result.append("Check.range(" + getRange(aField) + "), ");
108        }
109        else if( aField.getMinimum() != null ) {
110          result.append("Check.min(" + getMin(aField) + "), ");
111        }
112        else if ( aField.getMaximum() != null ) {
113          result.append("Check.max(" + getMax(aField) + "), ");
114        }
115        
116        if( aField.getNumDecimals() != null ) {
117          result.append("Check.numDecimalsAlways(" + aField.getNumDecimals() + "), ");
118        }
119        
120        if( aField.getCheckPattern() != null ){
121          result.append("Check.isRegex(), ");
122        }
123        
124        if ( aField.getCheckEmail() == true ){
125          result.append("Check.isEmail(), ");
126        }
127        
128        if( aField.getCheckSpam() == true ){
129          result.append("Check.isSpam(), ");
130        }
131        return result.toString();
132      }
133      
134      /**  Return a file:// URI for the given file.  */
135      public static String fileURL(String aFileName){
136        return "file:///" + aFileName.replace('\\', '/');
137      }
138      
139      // PRIVATE //
140      private static final char SPACE = ' ';
141      private static final char UNDERSCORE = '_';
142      
143      //prevent construction by the caller
144      private Functions() {}
145      
146      private static String firstLetterLowerCase(String aIdentifier){
147        String firstLetter = aIdentifier.substring(0,1);
148        return aIdentifier.replaceFirst(firstLetter, firstLetter.toLowerCase());
149      }
150      
151      private static String getMin(Field aField){
152        String result = aField.getMinimum().toString(); //default
153        if ( FieldType.BigDecimal == aField.getType()  ) {
154          result = "new BigDecimal(\"" + aField.getMinimum() + "\")";      
155        }
156        else if( FieldType.Decimal == aField.getType() ) {
157          result = "Decimal.from(\"" + aField.getMinimum() + "\")";      
158        }
159        return result;
160      }
161      
162      private static String getMax(Field aField){
163        String result = aField.getMaximum().toString(); //default
164        if ( FieldType.BigDecimal == aField.getType()  ) {
165          result = "new BigDecimal(\"" + aField.getMaximum() + "\")";      
166        }
167        else if( FieldType.Decimal == aField.getType() ) {
168          result = "Decimal.from(\"" + aField.getMaximum() + "\")";      
169        }
170        return result;
171      }
172      
173      private static String getRange(Field aField){
174        return getMin(aField) + ", " + getMax(aField);
175      }
176    }