Skip to content

Commit

Permalink
Rework plugin significantly. Persistent constraints, Command objects …
Browse files Browse the repository at this point in the history
…and Injection are all working better now.

Signed-off-by: Geoff Lane <geoff@zorched.net>
  • Loading branch information
geofflane committed May 9, 2010
1 parent b8ba6b9 commit 918149f
Show file tree
Hide file tree
Showing 19 changed files with 427 additions and 370 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
stacktrace.log
*.zip
reports
target
100 changes: 68 additions & 32 deletions ConstraintsGrailsPlugin.groovy
Expand Up @@ -14,11 +14,15 @@
* limitations under the License.
*/

import net.zorched.grails.plugins.validation.ConstraintArtefactHandler
import net.zorched.grails.plugins.validation.GrailsConstraintClass
import org.codehaus.groovy.grails.validation.ConstrainedProperty
import net.zorched.grails.plugins.validation.GrailsConstraintClass
import org.springframework.beans.factory.config.MethodInvokingFactoryBean
import net.zorched.grails.plugins.validation.ConstraintArtefactHandler
import net.zorched.constraints.UsZipConstraint
import net.zorched.constraints.UsPhoneConstraint
import net.zorched.constraints.SsnConstraint
import net.zorched.constraints.ComparisonConstraint
import net.zorched.grails.plugins.validation.CustomConstraintFactory
import net.zorched.constraints.*

class ConstraintsGrailsPlugin {
// the plugin version
Expand All @@ -39,7 +43,6 @@ class ConstraintsGrailsPlugin {
"grails-app/utils/net/zorched/test/**.groovy"
]

// TODO Fill in these fields
def author = "Geoff Lane"
def authorEmail = "geoff@zorched.net"
def title = "Custom domain constraints plugin"
Expand All @@ -51,14 +54,9 @@ class ConstraintsGrailsPlugin {
// URL to the plugin's documentation
def documentation = "http://grails.org/plugin/constraints"

def loadAfter = ['core', 'hibernate']

def watchedResources = [
"file:./grails-app/utils/**/*Constraint.groovy",
"file:./plugins/*/grails-app/utils/**/*Constraint.groovy"
]
// def loadAfter = ['core', 'hibernate', 'controllers']

// We can add provided constraints in this plugin using this
// We can add provided constraints in this plugin using this
def providedArtefacts = [
ComparisonConstraint,
SsnConstraint,
Expand All @@ -68,37 +66,75 @@ class ConstraintsGrailsPlugin {

def artefacts = [new ConstraintArtefactHandler()]

def onChange = {event ->
def doWithSpring = {
// TODO Implement runtime spring config (optional)
application.constraintClasses.each {constraintClass ->
configureConstraintBeans.delegate = delegate
configureConstraintBeans(constraintClass)
}
}

def doWithDynamicMethods = { applicationContext ->
// TODO Implement registering dynamic methods to classes (optional)
application.constraintClasses.each {constraintClass ->
setupConstraintProperties(constraintClass)

registerConstraint.delegate = delegate
registerConstraint(constraintClass, false)
}

manager.refreshPlugin('validation')
}


def onChange = { event ->
// TODO Implement code that is executed when any artefact that this plugin is
// watching is modified and reloaded. The event contains: event.source,
// event.application, event.manager, event.ctx, and event.plugin.

// XXX: Not sure if this works?
if (application.isArtefactOfType(ConstraintArtefactHandler.TYPE, event.source)) {
setupConstraintProperties(event.source)
application.addArtefact(ConstraintArtefactHandler.TYPE, event.source)
}
}

def doWithDynamicMethods = {applicationContext ->
println "Constraints: ${version}. Configuring custom constraints..."
def configureConstraintBeans = {GrailsConstraintClass constraintClass ->
// XXX: Not convinced this does anything
def fullName = constraintClass.fullName
"${fullName}Class"(MethodInvokingFactoryBean) {
targetObject = ref("grailsApplication", true)
targetMethod = "getArtefact"
arguments = [ConstraintArtefactHandler.TYPE, constraintClass.fullName]
}

boolean usingHibernate = manager.hasGrailsPlugin("hibernate")
for (GrailsConstraintClass c in application.constraintClasses) {
registerConstraint(c, usingHibernate, applicationContext)
"${fullName}"(ref("${fullName}Class")) {bean ->
bean.factoryMethod = "newInstance"
bean.autowire = true
}
}

// HACK: Couldn't get Command objects to work without it, load order didn't seem to help
manager.refreshPlugin('controllers')
def setupConstraintProperties = { constraintClass ->
Object params = null
Object hibernateTemplate = null
Object constraintOwningClass = null
String constraintPropertyName = null
constraintClass.clazz.metaClass {
setParams = {val -> params = val}
getParams = {-> return params}
setHibernateTemplate = {val -> hibernateTemplate = val}
getHibernateTemplate = {-> return hibernateTemplate}
setConstraintOwningClass = {val -> constraintOwningClass = val}
getConstraintOwningClass = {-> return constraintOwningClass}
setConstraintPropertyName = {val -> constraintPropertyName = val}
getConstraintPropertyName = {-> return constraintPropertyName}
}
}
private void registerConstraint(constraintClass, usingHibernate, applicationContext) {

def registerConstraint = { constraintClass, usingHibernate ->
def constraintName = constraintClass.name
// println "Loading constraint: $constraintClass.Name"

if (usingHibernate) {
// println "Hibernate plugin in use, allowing persistent constraints"
ConstrainedProperty.registerNewConstraint(constraintName,
new CustomConstraintFactory(applicationContext, constraintClass))
} else {
// Don't allow persistent constraints if hibernate is not being used
ConstrainedProperty.registerNewConstraint(constraintName,
new CustomConstraintFactory(constraintClass))
}
log.debug "Loading constraint: ${constraintClass.name}"

ConstrainedProperty.registerNewConstraint(constraintName, new CustomConstraintFactory(constraintClass, applicationContext))
}
}
10 changes: 6 additions & 4 deletions application.properties
@@ -1,6 +1,8 @@
#Grails Metadata file
#Thu Jan 07 19:52:32 CST 2010
app.grails.version=1.2.0
#Sat May 08 20:02:05 CDT 2010
app.grails.version=1.2.2
app.name=constraints
plugins.hibernate=1.2.0
plugins.tomcat=1.2.0
app.version=0.5
plugins.hibernate=1.2.2
plugins.tomcat=1.2.2
plugins.webflow=1.2.2
2 changes: 1 addition & 1 deletion grails-app/domain/net/zorched/test/Address.groovy
@@ -1,6 +1,6 @@
package net.zorched.test

class Address {
class Address implements Serializable {
String street
String zip
String phone
Expand Down
2 changes: 1 addition & 1 deletion grails-app/domain/net/zorched/test/Foo.groovy
Expand Up @@ -5,7 +5,7 @@ class Foo {
List baz

static constraints = {
bar(twoLong: true)
bar(twoLong: true, nullable:true)
baz(twoLong: true)
}
}
9 changes: 9 additions & 0 deletions grails-app/domain/net/zorched/test/InjectedDom.groovy
@@ -0,0 +1,9 @@
package net.zorched.test

class InjectedDom {
String foo

static constraints = {
foo(injected:true)
}
}
8 changes: 8 additions & 0 deletions grails-app/services/net/zorched/test/MyTestService.groovy
@@ -0,0 +1,8 @@
package net.zorched.test

class MyTestService {

def isSomething() {
return true
}
}
Expand Up @@ -25,6 +25,7 @@ class UsPhoneConstraint {
}

def validate = { val ->
System.out.println("Called UsPhoneConstraint.validate: ${val}")
if (! params)
return true
return val ==~ /^[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}$/
Expand Down
Expand Up @@ -25,8 +25,9 @@ class UsZipConstraint {
}

def validate = { val ->
System.out.println("Called UsZipConstraint.validate: ${val}")
if (! params)
return true
return val ==~ /^\d{5}(\-\d{4})?$/
}
}
}
1 change: 1 addition & 0 deletions grails-app/utils/net/zorched/test/AddressAnno.groovy
Expand Up @@ -15,6 +15,7 @@ public class AddressAnno {
String phone

static constraints = {
street(blank: false)
zip(usZip: true)
phone(usPhone: true)
}
Expand Down
10 changes: 10 additions & 0 deletions grails-app/utils/net/zorched/test/InjectedConstraint.groovy
@@ -0,0 +1,10 @@
package net.zorched.test

class InjectedConstraint {

def myTestService

def validate = { propertyValue, target ->
return myTestService.isSomething()
}
}
4 changes: 4 additions & 0 deletions grails-app/utils/net/zorched/test/TwoLongConstraint.groovy
Expand Up @@ -3,6 +3,10 @@ package net.zorched.test
class TwoLongConstraint {

def validate = { propertyValue, target ->
if (null == propertyValue) {
println "null propertyvalue"
return true
}
return propertyValue.size() == 2
}
}
4 changes: 2 additions & 2 deletions grails-app/utils/net/zorched/test/UniqueEgConstraint.groovy
Expand Up @@ -25,8 +25,8 @@ class UniqueEgConstraint {
shouldValidate = session.contains(propertyValue)
}
if(shouldValidate) {
Criteria criteria = session.createCriteria( constraintOwningClass )
.add(Restrictions.eq( constraintPropertyName, propertyValue ))
Criteria criteria = session.createCriteria(constraintOwningClass)
.add(Restrictions.eq(constraintPropertyName, propertyValue))
return criteria.list()
} else {
return null
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2009 the original author or authors.
* Copyright 2006-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,20 +21,19 @@
/**
* Grails artefact handler for constraint classes.
*
* @author Geoff Lane (geoff@zorched.net)
*
* @author Geofff Lane
* @since 0.1
*/
public class ConstraintArtefactHandler extends ArtefactHandlerAdapter {

public static final String TYPE = "Constraint";

public ConstraintArtefactHandler() {
super(TYPE, GrailsConstraintClass.class, DefaultGrailsConstraintClass.class, TYPE);
super(TYPE, GrailsConstraintClass.class, DefaultGrailsConstraintClass.class, null);
}

public boolean isArtefactClass(Class clazz) {
if (clazz == null) return false;
public boolean isArtefactClass(Class clazz) {
if (clazz == null) return false;
if (!clazz.getName().endsWith(DefaultGrailsConstraintClass.CONSTRAINT)) {
return false;
}
Expand Down

0 comments on commit 918149f

Please sign in to comment.