| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Grails
Revision: 7279
Author: pledbrook
Date: 11 Aug 2008 13:23:46
Changes:GRAILS-2741: Custom constraints provided by plugins are not available
when domain classes are initially processed (unless the plugin is loaded
before the domain class plugin), so the domain class constraints are
"refreshed" after all the plugins have loaded. The constraints of
embedded domain classes, though, weren't refreshed and so custom
constraints were not being triggered by the validation.
Now the DefaultGrailsDomainClass.refreshConstraints() method manually
refreshes the constraints of any component/embedded properties.
| ... | ...@@ -600,7 +600,14 @@ | |
| 600 | 600 | } |
| 601 | 601 | |
| 602 | 602 | public void refreshConstraints() { |
| 603 | // do nothing | |
| 603 | try { | |
| 604 | GrailsDomainClassProperty[] props = getPersistentProperties(); | |
| 605 | this.constraints = GrailsDomainConfigurationUtil.evaluateConstraints( | |
| 606 | getReference().getWrappedInstance(), | |
| 607 | props); | |
| 608 | } catch (IntrospectionException e) { | |
| 609 | LOG.error("Error reading class [" + getClazz() + "] constraints: " + e.getMessage(), e); | |
| 610 | } | |
| 604 | 611 | } |
| 605 | 612 | |
| 606 | 613 | public boolean hasSubClasses() { |
| ... | ...@@ -1,4 +1,7 @@ | |
| 1 | 1 | package org.codehaus.groovy.grails.orm.hibernate |
| 2 | ||
| 3 | import org.codehaus.groovy.grails.validation.ConstrainedProperty | |
| 4 | ||
| 2 | 5 | /** |
| 3 | 6 | * @author Graeme Rocher |
| 4 | 7 | * @since 1.0 |
| ... | ...@@ -33,7 +36,7 @@ | |
| 33 | 36 | static constraints = { |
| 34 | 37 | dateEntered(nullable:false) |
| 35 | 38 | dateUpdated(nullable:false) |
| 36 | enteredBy(nullable:false,maxSize:20) | |
| 39 | enteredBy(nullable:false,maxSize:20,custom: true) | |
| 37 | 40 | updatedBy(nullable:false,maxSize:20) |
| 38 | 41 | } |
| 39 | 42 | |
| ... | ...@@ -67,4 +70,63 @@ | |
| 67 | 70 | assert person.id != null |
| 68 | 71 | } |
| 69 | 72 | |
| 70 | } | |
| 71 | 73 | \ No newline at end of file |
| 74 | void testCustomConstraint() { | |
| 75 | def personClass = ga.getDomainClass("ComponentValidationTestsPerson").clazz | |
| 76 | def auditClass = ga.getDomainClass("ComponentValidationTestsAuditInfo").clazz | |
| 77 | ||
| 78 | // Load the custom constraint. | |
| 79 | def constraintClass = gcl.parseClass(''' | |
| 80 | import org.codehaus.groovy.grails.validation.AbstractConstraint | |
| 81 | import org.springframework.validation.Errors | |
| 82 | ||
| 83 | class CustomConstraint extends AbstractConstraint { | |
| 84 | boolean active | |
| 85 | String name = "custom" | |
| 86 | ||
| 87 | public void setParameter(Object constraintParameter) { | |
| 88 | assert constraintParameter instanceof Boolean | |
| 89 | ||
| 90 | this.active = constraintParameter.booleanValue() | |
| 91 | super.setParameter(constraintParameter) | |
| 92 | } | |
| 93 | ||
| 94 | protected void processValidate(Object target, Object propertyValue, Errors errors) { | |
| 95 | if (this.active) { | |
| 96 | if (propertyValue != "fred") { | |
| 97 | def args = [constraintPropertyName, constraintOwningClass, propertyValue] as Object[] | |
| 98 | super.rejectValue( | |
| 99 | target, | |
| 100 | errors, | |
| 101 | "some.error.message", | |
| 102 | "invalid.custom", | |
| 103 | args) | |
| 104 | } | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | boolean supports(Class type) { | |
| 109 | return type == String | |
| 110 | } | |
| 111 | } | |
| 112 | ''') | |
| 113 | ||
| 114 | // Register the new constraint. | |
| 115 | Class clazz = gcl.loadClass("org.codehaus.groovy.grails.validation.ConstrainedProperty") | |
| 116 | clazz.registerNewConstraint("custom", constraintClass) | |
| 117 | ||
| 118 | // Refresh the constraints now that we have registered a new one. | |
| 119 | ga.refreshConstraints() | |
| 120 | ||
| 121 | // Create the test domain instances. | |
| 122 | def person = personClass.newInstance() | |
| 123 | def date = new Date() | |
| 124 | person.name = 'graeme' | |
| 125 | person.auditInfo = auditClass.newInstance( | |
| 126 | dateEntered: date, | |
| 127 | dateUpdated: date, | |
| 128 | enteredBy: 'chris', | |
| 129 | updatedBy: 'chris') | |
| 130 | ||
| 131 | assertFalse "The validation should fail since the custom validator has been registered.", person.validate() | |
| 132 | } | |
| 133 | } |
| ... | ...@@ -42,7 +42,7 @@ | |
| 42 | 42 | private GrailsDomainClassProperty identifier; |
| 43 | 43 | private GrailsDomainClassProperty version; |
| 44 | 44 | private GrailsDomainClassProperty[] properties; |
| 45 | private GrailsDomainClassProperty[] persistantProperties; | |
| 45 | private GrailsDomainClassProperty[] persistentProperties; | |
| 46 | 46 | private Map propertyMap; |
| 47 | 47 | private Map relationshipMap; |
| 48 | 48 | |
| ... | ...@@ -97,11 +97,11 @@ | |
| 97 | 97 | // establish relationships |
| 98 | 98 | establishRelationships(); |
| 99 | 99 | |
| 100 | // set persistant properties | |
| 100 | // set persistent properties | |
| 101 | 101 | establishPersistentProperties(); |
| 102 | 102 | // process the constraints |
| 103 | 103 | try { |
| 104 | this.constraints = GrailsDomainConfigurationUtil.evaluateConstraints(getReference().getWrappedInstance(), this.persistantProperties); | |
| 104 | this.constraints = GrailsDomainConfigurationUtil.evaluateConstraints(getReference().getWrappedInstance(), this.persistentProperties); | |
| 105 | 105 | } catch (IntrospectionException e) { |
| 106 | 106 | LOG.error("Error reading class ["+getClazz()+"] constraints: " +e .getMessage(), e); |
| 107 | 107 | } |
| ... | ...@@ -127,7 +127,7 @@ | |
| 127 | 127 | tempList.add(currentProp); |
| 128 | 128 | } |
| 129 | 129 | } |
| 130 | this.persistantProperties = (GrailsDomainClassProperty[])tempList.toArray( new GrailsDomainClassProperty[tempList.size()]); | |
| 130 | this.persistentProperties = (GrailsDomainClassProperty[])tempList.toArray( new GrailsDomainClassProperty[tempList.size()]); | |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | /** |
| ... | ...@@ -590,11 +590,11 @@ | |
| 590 | 590 | * @deprecated |
| 591 | 591 | */ |
| 592 | 592 | public GrailsDomainClassProperty[] getPersistantProperties() { |
| 593 | return this.persistantProperties; | |
| 593 | return this.persistentProperties; | |
| 594 | 594 | } |
| 595 | 595 | |
| 596 | 596 | public GrailsDomainClassProperty[] getPersistentProperties() { |
| 597 | return this.persistantProperties; | |
| 597 | return this.persistentProperties; | |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | /* (non-Javadoc) |
| ... | ...@@ -695,7 +695,17 @@ | |
| 695 | 695 | |
| 696 | 696 | public void refreshConstraints() { |
| 697 | 697 | try { |
| 698 | this.constraints = GrailsDomainConfigurationUtil.evaluateConstraints(getReference().getWrappedInstance(), this.persistantProperties); | |
| 698 | this.constraints = GrailsDomainConfigurationUtil.evaluateConstraints(getReference().getWrappedInstance(), this.persistentProperties); | |
| 699 | ||
| 700 | // Embedded components have their own ComponentDomainClass | |
| 701 | // instance which won't be refreshed by the application. | |
| 702 | // So, we have to do it here. | |
| 703 | for (int i = 0; i < this.persistentProperties.length; i++) { | |
| 704 | GrailsDomainClassProperty property = this.persistentProperties[i]; | |
| 705 | if (property.isEmbedded()) { | |
| 706 | property.getComponent().refreshConstraints(); | |
| 707 | } | |
| 708 | } | |
| 699 | 709 | } catch (IntrospectionException e) { |
| 700 | 710 | LOG.error("Error reading class ["+getClazz()+"] constraints: " +e .getMessage(), e); |
| 701 | 711 | } |
| ... | ...@@ -706,9 +716,9 @@ | |
| 706 | 716 | } |
| 707 | 717 | |
| 708 | 718 | public boolean hasPersistentProperty(String propertyName) { |
| 709 | for (int i = 0; i < persistantProperties.length; i++) { | |
| 710 | GrailsDomainClassProperty persistantProperty = persistantProperties[i]; | |
| 711 | if(persistantProperty.getName().equals(propertyName)) return true; | |
| 719 | for (int i = 0; i < persistentProperties.length; i++) { | |
| 720 | GrailsDomainClassProperty persistentProperty = persistentProperties[i]; | |
| 721 | if(persistentProperty.getName().equals(propertyName)) return true; | |
| 712 | 722 | } |
| 713 | 723 | return false; |
| 714 | 724 | } |