I was recently given a requirement to drive the entity attribute validations at runtime rather than at design time, with the following criteria.
The key thing then is to use database dictionary views along with these database tables to validate attributes of the entity for a pattern (regular expression).
The class that contains the method to perform validations is CustomEntityImpl and each entity that one wants to enable for runtime validation must extend this class and call its validateCustomEntity method in its entity method validator.
In the sample application i have enabled a required and pattern constraint as shown in the following screenshots for dummy entity object’s attribute.
The application source and sql script can be downloaded from the below mentioned link.
Source Code
Note: If you want to test the application you must create tables under user “raman”.
Edit: To skip validation for existing attribute that has not been modified you can use the following snippet.
- Ability to change fields to required at runtime.
- To be able to define validation message for field at runtime
- Define validations such as field must be numeric, or contain only alphabets (Used Regular expression for this)
- Localization of validation messages
The key thing then is to use database dictionary views along with these database tables to validate attributes of the entity for a pattern (regular expression).
The class that contains the method to perform validations is CustomEntityImpl and each entity that one wants to enable for runtime validation must extend this class and call its validateCustomEntity method in its entity method validator.
protected Boolean validateCustomEntity(){ ResourceBundleDef rbd=getEntityDef().getResourceBundleDef(); PropertiesBundleDef pbd=null; if(rbd==null){ pbd = new PropertiesBundleDef(this.getEntityDef()); pbd.setPropertiesFile("com.blogspot.ramannanda.demos.validationapp.model.ModelBundle"); rbd=pbd; } ArrayList<RowValException> exceptions=new ArrayList<RowValException>(); EntityImpl entObj= this; String tableName=this.getEntityDef().getSource(); tableName=tableName.substring(tableName.lastIndexOf(".")+1,tableName.length()); AttributeDef[] attrDefs= this.getEntityDef().getAttributeDefs(); ValidationsVOImpl vo=(ValidationsVOImpl) this.getDBTransaction().getRootApplicationModule().findViewObject("ValidationsVO12"); ViewCriteriaManager vcm=vo.getViewCriteriaManager(); ViewCriteria vc=vcm.getViewCriteria("ValidationsVOCriteria"); vo.setbTableName(tableName); vo.applyViewCriteria(vc, false); vo.executeQuery(); RowSetIterator it=vo.createRowSetIterator(null); ArrayList<AttrValException> attrValExceptions=new ArrayList<AttrValException>(); while(it.hasNext()){ ValidationsVORowImpl row=(ValidationsVORowImpl)it.next(); String pattern=row.getValidationPattern(); String fieldName=row.getAttribName(); for(int i=0;i<attrDefs.length;i++){ String attrName=attrDefs[i].getName(); String columnName=attrDefs[i].getColumnName(); if(columnName.equals(fieldName)){ String attribRequired=row.getAttribRequired(); Object attribValue=entObj.getAttribute(attrName); ArrayList<JboException> list=new ArrayList<JboException>(2); if(attribRequired.equalsIgnoreCase("Y")) { if(attribValue==null || ((String)attribValue).isEmpty()){ String errorMessageKey=row.getRequiredMsgKey(); if(errorMessageKey!=null&&!errorMessageKey.isEmpty()){ JboException exception=new JboException(getMessageForKey(errorMessageKey),null,new Object[]{attrName}); list.add(exception); } else{ AttrSetValException exception= new AttrSetValException(AttrValException.TYP_DEF_ENTITY_OBJECT, rbd, "DEFAULT_REQUIRED_ERROR", entObj.getStructureDef().getFullName(), attrName,attribValue, null); list.add(exception); } } } if(((attribValue!=null)&& !((String)attribValue).isEmpty())){ boolean result=validatePattern(pattern,(String)entObj.getAttribute(attrName)); if(!result){ String errorMessageKey=row.getValidationMsgKey(); if(errorMessageKey!=null&&!errorMessageKey.isEmpty()){ JboException exception=new JboException(getMessageForKey(errorMessageKey),null,new Object[]{attrName,attribValue}); list.add(exception); list.add(exception); } else{ AttrSetValException exception= new AttrSetValException(AttrValException.TYP_DEF_ENTITY_OBJECT, rbd, "DEFAULT_INCORRECT_VAL_ERROR", entObj.getStructureDef().getFullName(), attrName,attribValue, null); list.add(exception); } } } if(list.size()>0){ AttrValException ave = new AttrValException(CSMessageBundle.class, CSMessageBundle.EXC_VAL_VR_VALIDATE_FAILED, entObj.getStructureDef().getFullName(), attrName,attribValue, list, false); attrValExceptions.add(ave); } } } } it.closeRowSetIterator(); if(attrValExceptions.size()>0){ RowValException rowValException= new RowValException(CSMessageBundle.class, CSMessageBundle.EXC_VAL_VR_VALIDATE_FAILED, entObj.getStructureDef().getFullName(), entObj.getKey(), attrValExceptions); exceptions.add(rowValException); } if(exceptions.size()>0){ throw new RowValException(CSMessageBundle.class, CSMessageBundle.EXC_VAL_VR_VALIDATE_FAILED, getStructureDef().getFullName(), getKey(), exceptions); } return true; } /** * This method returns false or true depending upon whether the field is valid or not * @param patternString * @param value */ private boolean validatePattern(String patternString, String value) { Pattern pattern =Pattern.compile(patternString); Matcher matcher= pattern.matcher(value); return matcher.matches(); } private String getMessageForKey(String msgKey){ Locale defaultLocale=Locale.US; String defaultMessage=null; String localMessage=null; Locale locale = this.getDBTransaction().getSession(). getLocale(); String localString=locale.toLanguageTag(); ValidationMessagesVOImpl vo=(ValidationMessagesVOImpl) this.getDBTransaction().getRootApplicationModule().findViewObject("ValidationMessagesVO12"); ViewCriteriaManager vcm=vo.getViewCriteriaManager(); ViewCriteria vc=vcm.getViewCriteria("ValidationMessagesVOCriteria1"); vo.setbMessageKey(msgKey); vo.applyViewCriteria(vc, false); vo.executeQuery(); RowSetIterator it=vo.createRowSetIterator(null); while(it.hasNext()){ ValidationMessagesVORowImpl row=(ValidationMessagesVORowImpl) it.next(); if(row.getMessageLocale().equals(defaultLocale.toLanguageTag())){ defaultMessage=row.getMessageText(); } if(row.getMessageLocale().equals(localString)){ localMessage=row.getMessageText(); break; } } it.closeRowSetIterator(); if(localMessage==null){ return defaultMessage; } return localMessage; }
In the sample application i have enabled a required and pattern constraint as shown in the following screenshots for dummy entity object’s attribute.
The application source and sql script can be downloaded from the below mentioned link.
Source Code
Note: If you want to test the application you must create tables under user “raman”.
Edit: To skip validation for existing attribute that has not been modified you can use the following snippet.
Object attribValue=getAttribute(attrName); int attribIndex=getAttributeIndexOf(attrName); Object oldAttribValue=getPostedAttribute(attribIndex); if(attribValue==null || !attribValue.equals(oldAttribValue)){
ArrayList<JboException> list=new ArrayList<JboException>(2); if(attribRequired.equalsIgnoreCase("Y")) { ....................