From: Eric C. <ecr...@us...> - 2006-09-25 19:25:04
|
User: ecrutchfield Date: 06/09/25 12:25:04 Modified: andromda-aspdotnet/src/main/resources/META-INF/andromda namespace.xml metafacades.xml profile.xml cartridge.xml andromda-aspdotnet/src/main/uml AspDotNetMetafacadeModelv4.xml.zip andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet CommonProperties.java andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet/metafacades AspParameterLogicImpl.java Added: andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet AspUtils.java andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet/metafacades AspAttributeLogicImpl.java Log: add support for parameter validation Revision Changes Path 1.2 +69 -0 cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/namespace.xml Index: namespace.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/namespace.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- namespace.xml 17 Sep 2006 17:30:42 -0000 1.1 +++ namespace.xml 25 Sep 2006 19:25:00 -0000 1.2 @@ -126,6 +126,20 @@ </property> </propertyGroup> <propertyGroup name="Other"> + <!-- property name="formClassPattern"> + <default>{0}{1}Form</default> + <documentation> + The pattern for constructing the name of the class under which the form (a.k.a the model) is stored, + where <em>{0}</em> is the name of the use case and <em>{1}</em> is the name of the trigger. + </documentation> + </property --> + <property name="controllerImplementationPattern"> + <default>{0}Impl</default> + <documentation> + The pattern for constructing the name of the controller implementation class name (where <em>{0}</em> + represents the modeled name of the controller). + </documentation> + </property> <property name="backingListPattern"> <default>{0}BackingList</default> <documentation> @@ -156,6 +170,13 @@ possible parameter values when selecting from a list). </documentation> </property> + <property name="fileTypeName"> + <default>System.IO.File</default> + <documentation> + The fully qualified type name to use when file types are modeled for parameters (used for + for file uploads). + </documentation> + </property> <property name="dummyData"> <default>false</default> <documentation> @@ -168,6 +189,54 @@ The text to render for 'todo' items in source code. </documentation> </property> + <property name="defaultInputColumnCount" required="false"> + <default>40</default> + <documentation> + If specified denotes the default length of text input fields, + the value specifies the <code>size</code> attribute of the corresponding + <code>input</code> or <code>textarea</code> element. + Not speciying any valid value will make the cartridge ignore it and resort + to the default browser value by not rendering any <code>size</code> attribute. + </documentation> + </property> + <property name="defaultInputRowCount" required="false"> + <default>5</default> + <documentation> + If specified denotes the default number of rows of <code>textarea</code> elements. + Not speciying any valid value will make the cartridge ignore it and resort + to the default browser value by not rendering any <code>size</code> attribute. + </documentation> + </property> + <property name="defaultDateFormat"> + <default>MM/dd/yyyy</default> + <documentation> + The default date format to use in case it has not been explicitely + specified, for event parameters. + The format is specified by the + <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">System.Globalization.DateTimeFormatInfo</a> + class from the .Net Framework. Please + refer to the documentation of that class for more information. This format is case-sensitive. + </documentation> + </property> + <property name="strictDateTimeFormat"> + <default>false</default> + <documentation> + Specifies whether or not date and time formats are to be strictly matched. + This property takes either true or false as values. If set to true all dates and times + entered by the end-user will fail validation if they do not strictly adhere to their given format. + </documentation> + </property> + <property name="defaultTimeFormat"> + <default>HH:mm</default> + <documentation> + The default time format to use when it has not been explicitely + specified for event parameters. + The format is specified by the + <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">System.Globalization.DateTimeFormatInfo</a> + class from the .Net Framework. Please + refer to the documentation of that class for more information. This format is case-sensitive. + </documentation> + </property> </propertyGroup> </properties> 1.2 +14 -1 cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/metafacades.xml Index: metafacades.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/metafacades.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- metafacades.xml 17 Sep 2006 17:30:43 -0000 1.1 +++ metafacades.xml 25 Sep 2006 19:25:00 -0000 1.2 @@ -17,7 +17,7 @@ <mapping> <property name="useCase"/> </mapping> - <!-- property reference="controllerImplementationPattern"/ --> + <property reference="controllerImplementationPattern"/> </metafacade> <metafacade class="org.andromda.cartridges.aspdotnet.metafacades.AspSessionObjectLogicImpl"> @@ -48,6 +48,19 @@ <property reference="backingValuePattern"/> <property reference="labelListPattern"/> <property reference="valueListPattern"/> + <property reference="defaultDateFormat"/> + <property reference="defaultTimeFormat"/> + <property reference="defaultInputColumnCount"/> + <property reference="defaultInputRowCount"/> + </metafacade> + <metafacade class="org.andromda.cartridges.aspdotnet.metafacades.AspAttributeLogicImpl"> + <mapping/> + <property reference="defaultDateFormat"/> + <property reference="defaultTimeFormat"/> + <property reference="backingListPattern"/> + <property reference="backingValuePattern"/> + <property reference="labelListPattern"/> + <property reference="valueListPattern"/> </metafacade> <!-- metafacade class="org.andromda.cartridges.aspdotnet.metafacades.AspTransitionLogicImpl"> 1.2 +74 -43 cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/profile.xml Index: profile.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/profile.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- profile.xml 17 Sep 2006 17:30:43 -0000 1.1 +++ profile.xml 25 Sep 2006 19:25:00 -0000 1.2 @@ -187,6 +187,7 @@ <value>checkbox</value> <value>radio</value> <value>multibox</value> + <value>file</value> </allowedValues> </element> <element name="INPUT_RESET"> @@ -202,52 +203,32 @@ <value>true</value> </allowedValues> </element> - <element name="INPUT_VALIDWHEN"> + <element name="INPUT_RADIO"> <documentation> - Additional validation to be performed, specify a - commons-validator condition here, see - <a href="http://struts.apache.org/userGuide/dev_validator.html" - target="_blank">Struts-Validator</a> and go to the section labeled - <code>http://struts.apache.org/userGuide/dev_validator.html</code>. The required - parentheses will automatically be placed around your condition. + Can be used in combination with the <code>@andromda.presentation.web.view.field.type=radio</code> + tagged value. Use it to specify the number of options to render, the values of these + options will always be the same, alternatively + you can specify a comma-separated list of runtime properties if you prefer the values + to be updateable at runtime. If this tagged value is not specified the cartridge will + assume it to have value '3'. </documentation> - <value>@andromda.presentation.web.view.field.validwhen</value> + <value>@andromda.presentation.view.field.radio</value> <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> <allowedValues> - <value>a Struts 'validwhen' condition</value> + <value>a strictly positive integer</value> + <value default="true">3</value> </allowedValues> </element> - <element name="INPUT_EQUAL"> + <element name="INPUT_CALENDAR"> <documentation> - Allows the comparison between 2 fields, this allows you to specify the - other field that a parameter must equal in order to be valid (like when - comparing two passwords) + Denotes the parameter of type <code>datatype::Date</code> is to be rendered with a calendar + popup next to it. </documentation> - <value>@andromda.presentation.web.view.field.equal</value> + <value>@andromda.presentation.web.view.field.calendar</value> <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> <allowedValues> - <value>a Struts 'validwhen' condition</value> - </allowedValues> - </element> - <element name="INPUT_VALIDATORS"> - <documentation> - Custom validation to be performed, you can add one or more of your own validators here. - Make sure you add your validator definitions in <code>validator-rules.xml</code>, - there is a <a href="../andromda-cartridges/index.html#mergeMappingsUri">merge point</a> - that can be used to have them automatically inserted. - Validator values look like this: <code>myValidator</code>, - <code>myValidator(myVar=myArg)</code>, - <code>myValidator(myVar=myArg,myVar2=myArg2)</code>, etc... - Specify each validator using a new value, don't specify all of them in a single value. - Be careful when using multiple validators with the same 'var' name, the last one - found will be used! Normally speaking this should not happen, so try to avoid it - (I recommend against using names used by known validators: minlength, - test, datePattern, ...) - </documentation> - <value>@andromda.presentation.web.view.field.validators</value> - <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> - <allowedValues> - <value>a call to one of your custom validators</value> + <value default="true">false</value> + <value>true</value> </allowedValues> </element> <element name="INPUT_TABLELINK"> @@ -322,6 +303,56 @@ <value>Comma-separated list of column names</value> </allowedValues> </element> + <element name="INPUT_VALIDWHEN"> + <documentation><![CDATA[ + Additional validation to be performed using a + <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.comparevalidator.aspx">CompareValidator</a> control. + The comparison can be to either a value (string, number, date) or to another parameter on the form. + ]]> + </documentation> + <value>@andromda.presentation.web.view.field.validwhen</value> + <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> + <allowedValues> + <value><![CDATA[A comparison in the following form: <Operator><ControlToCompare|ValueToCompare> + where Operator is either an <a href="http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.validationcompareoperator.aspx">ValidationCompareOperator Enumeration</a> + or an equivalent operator such as ==, <, >, etc.]]> + </value> + </allowedValues> + </element> + <element name="INPUT_EQUAL"> + <documentation> + Allows the comparison between 2 fields. This allows you to specify the + other field that a parameter must equal in order to be valid (like when + comparing two passwords) + </documentation> + <value>@andromda.presentation.web.view.field.equal</value> + <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> + <allowedValues> + <value>the name of the parameter to validate against</value> + </allowedValues> + </element> + <element name="INPUT_VALIDATORS"> + <documentation> + <font color="red">[Not yet implemented]</font> + Custom validation to be performed, you can add one or more of your own validators here. + Make sure you add your validator definitions in <code>validator-rules.xml</code>, + there is a <a href="../andromda-cartridges/index.html#mergeMappingsUri">merge point</a> + that can be used to have them automatically inserted. + Validator values look like this: <code>myValidator</code>, + <code>myValidator(myVar=myArg)</code>, + <code>myValidator(myVar=myArg,myVar2=myArg2)</code>, etc... + Specify each validator using a new value, don't specify all of them in a single value. + Be careful when using multiple validators with the same 'var' name, the last one + found will be used! Normally speaking this should not happen, so try to avoid it + (I recommend against using names used by known validators: minlength, + test, datePattern, ...) + </documentation> + <value>@andromda.presentation.web.view.field.validators</value> + <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> + <allowedValues> + <value>a call to one of your custom validators</value> + </allowedValues> + </element> <element name="INPUT_REQUIRED"> <documentation> Denotes whether or not this is a required field. If a field is required its type will always be @@ -395,14 +426,14 @@ </tr> <tr> <td>System.String</td> - <td>creditcard</td> + <td><font color="red">[Not yet implemented]</font> creditcard</td> <td>N/A</td> <td>creditcard</td> <td>Validates the value to be a creditcard number, according to what is known as the Luhn check</td> </tr> <tr> <td>System.String</td> - <td>email</td> + <td><font color="red">[Not yet implemented]</font> email</td> <td>N/A</td> <td>email</td> <td>Checks if the specified value is a possible email address, IP addresses are also taken into account</td> @@ -410,10 +441,10 @@ </table> </p> <p> - (*) The format is specified by the System.Globalization.DateTimeFormatInfo class from the .Net Framework, please - refer to the documentation of that class for more information. This format is case-sensitive - <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp"> - DateTimeFormatInfo Class</a> + (*) The format is specified by the + <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">System.Globalization.DateTimeFormatInfo</a> + class from the .Net Framework. Please refer to the documentation of that class for more + information. This format is case-sensitive. <br/> (**) The pattern expression is a Perl regular expression as you would you use in Javascript, by convention it requires the ^ and $ to denote respectively the beginning and ending of the pattern @@ -421,7 +452,7 @@ Netscape's guide to regular expressions in Javascript</a> </p> </documentation> - <value>@andromda.presentation.web.view.field.format</value> + <value>@andromda.presentation.view.field.format</value> <appliedOnElement>Parameter coming out of an action state carrying the <![CDATA[<<FrontEndView>>]]> stereotype</appliedOnElement> <allowedValues> <value>Any of the formats listed above</value> 1.2 +10 -19 cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/cartridge.xml Index: cartridge.xml =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-aspdotnet/src/main/resources/META-INF/andromda/cartridge.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- cartridge.xml 17 Sep 2006 17:30:43 -0000 1.1 +++ cartridge.xml 25 Sep 2006 19:25:00 -0000 1.2 @@ -1,10 +1,13 @@ <cartridge> <templateEngine className="org.andromda.templateengines.velocity.VelocityTemplateEngine"> <macrolibrary name="templates/aspdotnet/web2003/renderFormInput.vm"/> + <macrolibrary name="templates/aspdotnet/web2005/renderFormInput.vm"/> + <macrolibrary name="templates/aspdotnet/web2003/tables.vm"/> + <macrolibrary name="templates/aspdotnet/web2005/tables.vm"/> + <macrolibrary name="templates/aspdotnet/validation.vm"/> <macrolibrary name="templates/aspdotnet/uicontrollers/formImplMacros.vm"/> <macrolibrary name="templates/aspdotnet/uicontrollers/formMacros.vm"/> <macrolibrary name="templates/aspdotnet/uicontrollers/Controller.cs.vm"/> - <!--macrolibrary name="templates/aspdotnet/web2005/renderActionCommandLinkParameter.vm"/--> <!-- cartridge-macrolibrary merge-point--> </templateEngine> @@ -38,13 +41,15 @@ <property reference="valueListPattern"/> <property reference="backingListPattern"/> <property reference="backingValuePattern"/> - + <property reference="fileTypeName"/> + <property reference="defaultDateFormat"/> + <property reference="defaultTimeFormat"/> <!-- cartridge-property merge-point --> + <condition name="is2003Solution">$dotNetVersion.equalsIgnoreCase("1.1")</condition> <condition name="is2005Solution">$dotNetVersion.equalsIgnoreCase("2.0")</condition> <!-- condition merge-point--> - <!-- cartridge-resource merge-point --> <resource path="calendar/*.*" outputPattern="calendar/{0}" @@ -68,6 +73,7 @@ outlet="web" outputCondition="is2005Solution" overwrite="false"/> + <!-- cartridge-resource merge-point --> <!-- .NET 1.1 templates --> <!-- this will generate the default page of the application--> @@ -393,22 +399,6 @@ </modelElements> </template --> - <!-- template - path="templates/aspdotnet/web2005/table.ascx.vsl" - outputPattern="${table.view.path}-${table.name}.ascx" - outlet="web_generated" - outputCondition="is2005Solution" - overwrite="true"> - <modelElements variable="table"> - <modelElement> - <type name="org.andromda.metafacades.uml.FrontEndParameter"> - <property name="table"/> - <property name="view"/> - </type> - </modelElement> - </modelElements> - </template --> - <template path="templates/aspdotnet/web2005/global.asax.vsl" outputPattern="global.asax" @@ -608,5 +598,6 @@ </modelElement> </modelElements> </template> + <!-- cartridge-template merge-point--> </cartridge> \ No newline at end of file 1.2 +132 -94 cartridges/andromda-aspdotnet/src/main/uml/AspDotNetMetafacadeModelv4.xml.zip <<Binary file>> 1.2 +44 -4 cartridges/andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet/CommonProperties.java Index: CommonProperties.java =================================================================== RCS file: /cvsroot/andromdaplugins/cartridges/andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet/CommonProperties.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- CommonProperties.java 17 Sep 2006 17:30:10 -0000 1.1 +++ CommonProperties.java 25 Sep 2006 19:25:03 -0000 1.2 @@ -11,6 +11,30 @@ public static final String FIELD_TYPE_TEXT = "textbox"; public static final String FIELD_TYPE_HIDDEN = "hidden"; public static final String FIELD_TYPE_LABEL = "plaintext"; + public static final String FIELD_TYPE_FILE = "file"; + public static final String FIELD_TYPE_PLAINTEXT = "plaintext"; + + public static final String VALID_WHEN_EQUAL = "=="; + public static final String VALID_WHEN_NOTEQUAL = "!="; + public static final String VALID_WHEN_GREATERTHAN = ">"; + public static final String VALID_WHEN_GREATERTHANEQUAL = ">="; + public static final String VALID_WHEN_LESSTHAN = "<"; + public static final String VALID_WHEN_LESSTHANEQUAL = "<="; + + public static final String VALID_WHEN_FIELD_NUMBER = "Integer"; + public static final String VALID_WHEN_FIELD_PARAMETER = "param"; + public static final String VALID_WHEN_FIELD_DATE = "Date"; + public static final String VALID_WHEN_FIELD_STRING = "String"; + + /** + * The pattern for constructing the class name under which the form is stored. + */ + public static final String FORM_CLASS_PATTERN = "formClassPattern"; + + /** + * Stores the pattern used for constructing the controller implementation name. + */ + public static final String CONTROLLER_IMPLEMENTATION_PATTERN = "controllerImplementationPattern"; /** * The pattern used for constructing a parameter's backing list name. A backing list @@ -38,8 +62,26 @@ */ public static final String BACKING_VALUE_PATTERN = "backingValuePattern"; - public static final String FIELD_CALENDAR = "@andromda.presentation.web.view.field.calendar"; - public static final String FIELD_VALIDATOR = "@andromda.presentation.view.field.validator"; + /** + * The default number of columns to render for TextBox fields. + */ + public static final String PROPERTY_DEFAULT_INPUT_COLUMN_COUNT = "defaultInputColumnCount"; + + /** + * The default number of rows to render for TextBox fields. + */ + public static final String PROPERTY_DEFAULT_INPUT_ROW_COUNT = "defaultInputRowCount"; + + /** + * Stores the default date format when dates are formatted. + */ + public static final String PROPERTY_DEFAULT_DATEFORMAT = "defaultDateFormat"; + + /** + * Stores the default time format when times are formatted. + */ + public static final String PROPERTY_DEFAULT_TIMEFORMAT = "defaultTimeFormat"; + public static final String WEB_ACTION_HYPERLINK = "hyperlink"; /** @@ -62,7 +104,5 @@ */ public static final String INPUT_TABLE = "table"; - public static final String WEB_TABLE_COLUMNS = "@andromda.presentation.view.table.columns"; - public static final String RADIO_BUTTON_GROUP = "@andromda.presentation.view.field.radio"; public static final String WEB_MENU_GROUP = "@andromda.presentation.web.menu.group"; } 1.1 cartridges/andromda-aspdotnet/src/main/java/org/andromda/cartridges/aspdotnet/AspUtils.java Index: AspUtils.java =================================================================== package org.andromda.cartridges.aspdotnet; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.andromda.cartridges.aspdotnet.metafacades.*; import org.andromda.metafacades.uml.*; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; /** * Utilties for use within the ASP.NET cartridge. * * @author Most of this code was originally written by Chad Brandon * @author Eric Crutchfield */ public class AspUtils { /** * The logger instance that can be used by all decendant classes. */ protected static Logger logger = Logger.getLogger(AspUtils.class); private static final Pattern VALIDATOR_TAGGEDVALUE_PATTERN = Pattern.compile("\\w+(\\(\\w+=[^,)]*(,\\w+=[^,)]*)*\\))?"); /** * Reads the validator arguments from the the given tagged value. * * @return returns a list of String instances or an empty list * @throws IllegalArgumentException when the input string does not match the required pattern */ public static List parseValidatorArgs(String validatorTaggedValue) { if (validatorTaggedValue == null) { throw new IllegalArgumentException("Validator tagged value cannot be null"); } // check if the input tagged value matches the required pattern if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches()) { throw new IllegalArgumentException( "Illegal validator tagged value (this tag is used to specify custom validators " + "and might look like myValidator(myVar=myArg,myVar2=myArg2), perhaps you wanted to use " + "@andromda.presentation.view.field.format?): " + validatorTaggedValue); } final List validatorArgs = new ArrayList(); // only keep what is between parentheses (if any) int left = validatorTaggedValue.indexOf('('); if (left > -1) { final int right = validatorTaggedValue.indexOf(')'); validatorTaggedValue = validatorTaggedValue.substring( left + 1, right); final String[] pairs = validatorTaggedValue.split(","); for (int i = 0; i < pairs.length; i++) { final String pair = pairs[i]; final int equalsIndex = pair.indexOf('='); // it's possible the argument is the empty string if (equalsIndex < pair.length() - 1) { validatorArgs.add(pair.substring(equalsIndex + 1)); } else { validatorArgs.add(""); } } } return validatorArgs; } /** * Reads the validator variable names from the the given tagged value. * * @return never null, returns a list of String instances * @throws IllegalArgumentException when the input string does not match the required pattern */ public static List parseValidatorVars(String validatorTaggedValue) { if (validatorTaggedValue == null) { throw new IllegalArgumentException("Validator tagged value cannot be null"); } // check if the input tagged value matches the required pattern if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches()) { throw new IllegalArgumentException("Illegal validator tagged value: " + validatorTaggedValue); } final List validatorVars = new ArrayList(); // only keep what is between parentheses (if any) int left = validatorTaggedValue.indexOf('('); if (left > -1) { int right = validatorTaggedValue.indexOf(')'); validatorTaggedValue = validatorTaggedValue.substring( left + 1, right); final String[] pairs = validatorTaggedValue.split(","); for (int i = 0; i < pairs.length; i++) { final String pair = pairs[i]; final int equalsIndex = pair.indexOf('='); validatorVars.add(pair.substring( 0, equalsIndex)); } } return validatorVars; } /** * Parses the validator name for a tagged value. * * @throws IllegalArgumentException when the input string does not match the required pattern */ public static String parseValidatorName(final String validatorTaggedValue) { if (validatorTaggedValue == null) { throw new IllegalArgumentException("Validator tagged value cannot be null"); } // check if the input tagged value matches the required pattern if (!VALIDATOR_TAGGEDVALUE_PATTERN.matcher(validatorTaggedValue).matches()) { throw new IllegalArgumentException("Illegal validator tagged value: " + validatorTaggedValue); } final int leftParen = validatorTaggedValue.indexOf('('); return (leftParen == -1) ? validatorTaggedValue : validatorTaggedValue.substring( 0, leftParen); } /** * @return this field's date format */ public static String getDateFormat(String format) { format = StringUtils.trimToEmpty(format); return format.endsWith(STRICT) ? getToken( format, 1, 2) : getToken( format, 0, 1); } private static final String STRICT = "strict"; /** * @return <code>true</code> if this field's value needs to conform to a strict date format, <code>false</code> otherwise */ public static boolean isStrictDateFormat(String format) { return strictDateTimeFormat ? strictDateTimeFormat : STRICT.equalsIgnoreCase(getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is an email format. * * @return <code>true</code> if this field is to be formatted as an email address, <code>false</code> otherwise */ public static boolean isEmailFormat(String format) { return "email".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is an equal format. * * @return <code>true</code> if this field is to be formatted as an email address, <code>false</code> otherwise */ public static boolean isEqualFormat(String format) { return "equal".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is a creditcard format. * * @return <code>true</code> if this field is to be formatted as a credit card, <code>false</code> otherwise */ public static boolean isCreditCardFormat(final String format) { return "creditcard".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is a pattern format. * * @return <code>true</code> if this field's value needs to respect a certain pattern, <code>false</code> otherwise */ public static boolean isPatternFormat(final String format) { return "pattern".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is a minlength format. * * @return <code>true</code> if this field's value needs to consist of at least a certain * number of characters, <code>false</code> otherwise */ public static boolean isMinLengthFormat(final String format) { return "minlength".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * Indicates if the given <code>format</code> is a maxlength format. * * @return <code>true</code> if this field's value needs to consist of at maximum a certain * number of characters, <code>false</code> otherwise */ public static boolean isMaxLengthFormat(String format) { return "maxlength".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * @return the i-th space delimited token read from the argument String, where i does not exceed the specified limit */ public static String getToken( String string, int index, int limit) { String token = null; if (string != null && string.length() > 0) { final String[] tokens = string.split( "[\\s]+", limit); token = index >= tokens.length ? null : tokens[index]; } return token; } /** * Retrieves the input format (if one is defined), for the given * <code>element</code>. * @param element the model element for which to retrieve the input format. * @return the input format. */ public static String getInputFormat(final ModelElementFacade element) { final Object value = element.findTaggedValue(AspProfile.TAGGEDVALUE_INPUT_FORMAT); final String format = value == null ? null : String.valueOf(value); return format == null ? null : format.trim(); } /** * Indicates if the given <code>format</code> is a range format. * * @return <code>true</code> if this field's value needs to be in a specific range, <code>false</code> otherwise */ public static boolean isRangeFormat(final String format) { return "range".equalsIgnoreCase(AspUtils.getToken( format, 0, 2)); } /** * @return <code>true</code> if the type of this field is a byte, <code>false</code> otherwise */ public static boolean isByte(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.BYTE_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a short, <code>false</code> otherwise */ public static boolean isShort(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.SHORT_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is an integer, <code>false</code> otherwise */ public static boolean isInteger(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.INTEGER_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a long integer, <code>false</code> otherwise */ public static boolean isLong(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.LONG_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a floating point, <code>false</code> otherwise */ public static boolean isFloat(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.FLOAT_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a double precision floating point, <code>false</code> otherwise */ public static boolean isDouble(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.DOUBLE_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a date, <code>false</code> otherwise */ public static boolean isDate(final ClassifierFacade type) { return type != null && type.isDateType(); } /** * @return <code>true</code> if the type of this field is a time, <code>false</code> otherwise */ public static boolean isTime(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.TIME_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a URL, <code>false</code> otherwise */ public static boolean isUrl(final ClassifierFacade type) { return UMLMetafacadeUtils.isType( type, AspProfile.URL_TYPE_NAME); } /** * @return <code>true</code> if the type of this field is a String, <code>false</code> otherwise */ public static boolean isString(final ClassifierFacade type) { return type != null && type.isStringType(); } /** * Indicates if the given element is read-only or not. * * @param element the element to check. * @return true/false */ public static boolean isReadOnly(final ModelElementFacade element) { boolean readOnly = false; if (element != null) { final Object value = element.findTaggedValue(AspProfile.TAGGEDVALUE_INPUT_READONLY); readOnly = Boolean.valueOf(ObjectUtils.toString(value)).booleanValue(); } return readOnly; } /** * Retrieves the "equal" value from the given element (if one is present). * * @param element the element from which to retrieve the equal value. * @return the "equal" value. */ public static java.lang.String getEqual(final ModelElementFacade element) { String equal = null; if (element != null) { final Object value = element.findTaggedValue(AspProfile.TAGGEDVALUE_INPUT_EQUAL); equal = value == null ? null : value.toString(); } return equal; } /** * Retrieves the "validwhen" value from the given element (if one is present). * * @param element the element from which to retrieve the validwhen value. * @return an array with 3 values: comparison, value/field to compare, and the * comparison type (i.e. field, value). */ public static java.lang.Object[] getValidWhen(final ModelElementFacade element) { Object[] validWhen = null; if (element != null) { //logger.info("Processing validWhen"); final Object value = element.findTaggedValue(AspProfile.TAGGEDVALUE_INPUT_VALIDWHEN); final String val1 = value == null ? null : value.toString(); if (val1 != null) { //ignore the first parameter if it's 'text' int startPos = 0; final String firstToken = AspUtils.getToken(val1, startPos, 2); //logger.info("Processing validWhen for string " + val1.toString()); if (firstToken != null && firstToken.trim().equalsIgnoreCase("text")) startPos = 1; final String operator = AspUtils.getToken(val1, startPos, 3).trim(); if (operator != null) logger.debug("Found an operator for the validWhen TV: " + operator.toString()); String field = AspUtils.getToken(val1, startPos + 1, 3).trim(); if (field != null) logger.debug("Found a field for the validWhen TV: " + field.toString()); if (operator != null && (operator.equals(CommonProperties.VALID_WHEN_EQUAL) || operator.equals(CommonProperties.VALID_WHEN_NOTEQUAL) || operator.equals(CommonProperties.VALID_WHEN_GREATERTHAN) || operator.equals(CommonProperties.VALID_WHEN_GREATERTHANEQUAL) || operator.equals(CommonProperties.VALID_WHEN_LESSTHAN) || operator.equals(CommonProperties.VALID_WHEN_LESSTHANEQUAL))) { String fieldType = null; try { if (field != null) { long number = java.lang.Long.parseLong(field); fieldType = CommonProperties.VALID_WHEN_FIELD_NUMBER; } } catch (NumberFormatException ex) { //do nothing } if (fieldType == null) { try { if (field != null) { java.util.Date date = java.text.DateFormat.getDateInstance().parse(field); fieldType = CommonProperties.VALID_WHEN_FIELD_DATE; } } catch (java.text.ParseException ex) { //do nothing } } if (fieldType == null) { if (field != null && field.equalsIgnoreCase("null")) { fieldType = CommonProperties.VALID_WHEN_FIELD_STRING; field = ""; } } if (fieldType == null) { fieldType = CommonProperties.VALID_WHEN_FIELD_PARAMETER; } logger.debug("The validWhen expression has been parsed as follows: operator = " + operator.toString() + " field = " + field.toString() + "fieldType = " + fieldType.toString()); validWhen = new Object[] {operator, field, fieldType}; } else { logger.error("The validWhen expression ('" + val1 + "') used on " + element.getName() + " is invalid."); } } } //logger.info("Finished processing validWhen. "); return validWhen; } /** * @return the lower limit for this field's value's range */ public static String getRangeStart(final String format) { return AspUtils.getToken( format, 1, 3); } /** * @return the upper limit for this field's value's range */ public static String getRangeEnd(final String format) { return AspUtils.getToken( format, 2, 3); } /** * @return the minimum number of characters this field's value must consist of */ public static String getMinLengthValue(final String format) { return AspUtils.getToken( format, 1, 2); } /** * @return the maximum number of characters this field's value must consist of */ public static String getMaxLengthValue(final String format) { return AspUtils.getToken( format, 1, 2); } /** * @return the pattern this field's value must respect */ public static String getPatternValue(final String format) { return '^' + AspUtils.getToken( format, 1, 2) + '$'; } /** * Retrieves the validator types as a collection from the given * <code>element</code> (if any can be retrieved). * * @param element the element from which to retrieve the types. * @param type the type of the element. * @return the collection of validator types. */ public static java.util.Collection getValidatorTypes( final ModelElementFacade element, final ClassifierFacade type) { final Collection validatorTypesList = new ArrayList(); if (element != null && type != null) { final String format = AspUtils.getInputFormat(element); final boolean isRangeFormat = format != null && isRangeFormat(format); if (element instanceof AspParameter) { if (((AspParameter)element).isRequired()) { validatorTypesList.add("required"); } } if (AspUtils.isByte(type)) { validatorTypesList.add("byte"); } else if (AspUtils.isShort(type)) { validatorTypesList.add("short"); } else if (AspUtils.isInteger(type)) { validatorTypesList.add("integer"); } else if (AspUtils.isLong(type)) { validatorTypesList.add("long"); } else if (AspUtils.isFloat(type)) { validatorTypesList.add("float"); } else if (AspUtils.isDouble(type)) { validatorTypesList.add("double"); } else if (AspUtils.isDate(type)) { validatorTypesList.add("date"); } else if (AspUtils.isTime(type)) { validatorTypesList.add("time"); } else if (AspUtils.isUrl(type)) { validatorTypesList.add("url"); } if (isRangeFormat) { if (AspUtils.isInteger(type) || AspUtils.isShort(type) || AspUtils.isLong(type)) { validatorTypesList.add("intRange"); } if (AspUtils.isFloat(type)) { validatorTypesList.add("floatRange"); } if (AspUtils.isDouble(type)) { validatorTypesList.add("doubleRange"); } } if (format != null) { if (AspUtils.isString(type) && AspUtils.isEmailFormat(format)) { validatorTypesList.add("email"); } else if (AspUtils.isString(type) && AspUtils.isCreditCardFormat(format)) { validatorTypesList.add("creditCard"); } else { Collection formats = element.findTaggedValues(AspProfile.TAGGEDVALUE_INPUT_FORMAT); for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();) { String additionalFormat = String.valueOf(formatIterator.next()); if (AspUtils.isMinLengthFormat(additionalFormat)) { validatorTypesList.add("minlength"); } else if (AspUtils.isMaxLengthFormat(additionalFormat)) { validatorTypesList.add("maxlength"); } else if (AspUtils.isPatternFormat(additionalFormat)) { validatorTypesList.add("mask"); } } } } if (AspUtils.getValidWhen(element) != null) { validatorTypesList.add("validwhen"); } if (AspUtils.getEqual(element) != null) { validatorTypesList.add("equal"); } } // - custom (paramterized) validators are allowed here final Collection taggedValues = element.findTaggedValues(AspProfile.TAGGEDVALUE_INPUT_VALIDATORS); for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();) { String validator = String.valueOf(iterator.next()); validatorTypesList.add(AspUtils.parseValidatorName(validator)); } return validatorTypesList; } /** * Gets the validator variables for the given <code>element</code> (if they can * be retrieved). * * @param element the element from which to retrieve the variables * @param type the type of the element. * @return the collection of validator variables. */ public static java.util.Collection getValidatorVars( final ModelElementFacade element, final ClassifierFacade type) { final Map vars = new LinkedHashMap(); if (element != null && type != null) { final String format = AspUtils.getInputFormat(element); if (format != null) { final boolean isRangeFormat = AspUtils.isRangeFormat(format); if (isRangeFormat) { final String min = "min"; final String max = "max"; vars.put( min, Arrays.asList(new Object[] {min, AspUtils.getRangeStart(format)})); vars.put( max, Arrays.asList(new Object[] {max, AspUtils.getRangeEnd(format)})); } else { final Collection formats = element.findTaggedValues(AspProfile.TAGGEDVALUE_INPUT_FORMAT); for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();) { final String additionalFormat = String.valueOf(formatIterator.next()); final String minlength = "minlength"; final String maxlength = "maxlength"; final String mask = "mask"; if (AspUtils.isMinLengthFormat(additionalFormat)) { vars.put( minlength, Arrays.asList(new Object[] {minlength, AspUtils.getMinLengthValue(additionalFormat)})); } else if (AspUtils.isMaxLengthFormat(additionalFormat)) { vars.put( maxlength, Arrays.asList(new Object[] {maxlength, AspUtils.getMaxLengthValue(additionalFormat)})); } else if (AspUtils.isPatternFormat(additionalFormat)) { vars.put( mask, Arrays.asList(new Object[] {mask, AspUtils.getPatternValue(additionalFormat)})); } } } } String inputFormat; if (element instanceof AspParameter) { inputFormat = ((AspParameter)element).getFormat(); } else { throw new RuntimeException("'element' is an invalid type, it must be an instance of '" + AspParameter.class.getName() + "'"); } if (AspUtils.isDate(type)) { final String datePatternStrict = "datePatternStrict"; if (format != null && AspUtils.isStrictDateFormat(format)) { vars.put( datePatternStrict, Arrays.asList(new Object[] {datePatternStrict, inputFormat})); } else { final String datePattern = "datePattern"; vars.put( datePattern, Arrays.asList(new Object[] {datePattern, inputFormat})); } } if (AspUtils.isTime(type)) { final String timePattern = "timePattern"; vars.put( timePattern, Arrays.asList(new Object[] {timePattern, inputFormat})); } final Object[] validWhen = AspUtils.getValidWhen(element); if (validWhen != null) { final String test = "test"; vars.put( test, Arrays.asList(validWhen)); } final String equal = AspUtils.getEqual(element); if (equal != null) { final String fieldName = "fieldName"; vars.put( fieldName, Arrays.asList(new Object[] {fieldName, equal})); } } // - custom (parameterized) validators are allowed here // in this case we will reuse the validator arg values final Collection taggedValues = element.findTaggedValues(AspProfile.TAGGEDVALUE_INPUT_VALIDATORS); for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();) { final String validator = String.valueOf(iterator.next()); // - guaranteed to be of the same length final List validatorVars = AspUtils.parseValidatorVars(validator); final List validatorArgs = AspUtils.parseValidatorArgs(validator); for (int ctr = 0; ctr < validatorVars.size(); ctr++) { final String validatorVar = (String)validatorVars.get(ctr); final String validatorArg = (String)validatorArgs.get(ctr); vars.put( validatorVar, Arrays.asList(new Object[] {validatorVar, validatorArg})); } } return vars.values(); } /** * Gets the validator args for the <code>element</code> and the given <code>validatorType</code>. * * @param element the element for which to retrieve the arguments. * @param validatorType the validator type name. * @return the validator args as a collection. */ public static java.util.Collection getValidatorArgs( final ModelElementFacade element, final java.lang.String validatorType) { final Collection args = new ArrayList(); if ("intRange".equals(validatorType) || "floatRange".equals(validatorType) || "doubleRange".equals(validatorType)) { args.add("${var:min}"); args.add("${var:max}"); } else if ("minlength".equals(validatorType)) { args.add("${var:minlength}"); } else if ("maxlength".equals(... [truncated message content] |