Merge branch '3.x' Conflicts: grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy
diff --git a/boot-plugins/gorm-hibernate4-spring-boot/build.gradle b/boot-plugins/gorm-hibernate4-spring-boot/build.gradle index 975b25f..43fb987 100644 --- a/boot-plugins/gorm-hibernate4-spring-boot/build.gradle +++ b/boot-plugins/gorm-hibernate4-spring-boot/build.gradle
@@ -1,7 +1,7 @@ apply from:'../gradle/maven-central-build.gradle' group = 'org.grails' -version = "1.1.0.RELEASE" +version = "4.0.0.BUILD-SNAPSHOT" sourceCompatibility = 1.6 targetCompatibility = 1.6
diff --git a/boot-plugins/gorm-mongodb-spring-boot/build.gradle b/boot-plugins/gorm-mongodb-spring-boot/build.gradle index 506b398..1104605 100644 --- a/boot-plugins/gorm-mongodb-spring-boot/build.gradle +++ b/boot-plugins/gorm-mongodb-spring-boot/build.gradle
@@ -1,7 +1,7 @@ apply from:'../gradle/maven-central-build.gradle' group = 'org.grails' -version = "1.1.0.RELEASE" +version = "4.0.0.BUILD-SNAPSHOT" sourceCompatibility = 1.6 targetCompatibility = 1.6
diff --git a/build.gradle b/build.gradle index c2ba14e..35d867f 100644 --- a/build.gradle +++ b/build.gradle
@@ -1,13 +1,13 @@ project.ext { - springVersion = "3.2.9.RELEASE" - grailsVersion = "2.3.11" + springVersion = "4.1.2.RELEASE" + grailsVersion = "3.0.0.BUILD-SNAPSHOT" slf4jVersion = "1.7.5" junitVersion = "4.11" - groovyVersion = System.getProperty('groovyVersion') ?: '2.1.9' + groovyVersion = System.getProperty('groovyVersion') ?: '2.3.6' isTravisBuild = System.getenv().get("TRAVIS") == 'true' - projectVersion = "3.1.4" - // releaseType = "RELEASE" + projectVersion = "4.0.0" +// releaseType = "RELEASE" releaseType = "BUILD-SNAPSHOT" isCiBuild = project.hasProperty("isCiBuild") isBuildSnapshot = releaseType == "BUILD-SNAPSHOT" @@ -67,13 +67,9 @@ } } -task wrapper(type: Wrapper) { - gradleVersion = '1.9' -} - subprojects { if(project.name.endsWith("spring-boot")) return - afterEvaluate { project -> + afterEvaluate { project -> if (isGroovyProject(project)) { def hasSnapshotVersion = project.version.endsWith("-SNAPSHOT") if(isBuildSnapshot != hasSnapshotVersion) { @@ -86,6 +82,7 @@ project.ext.artifactoryPublishPassword = System.getenv("ARTIFACTORY_PASSWORD") } + version = "${projectVersion}.${releaseType}" group = "org.grails" @@ -127,16 +124,26 @@ dependencies { if (isStandardGroovyMavenProject) { - groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: groovyVersion + groovy group: 'org.codehaus.groovy', name: 'groovy', version: groovyVersion + + testCompile group: 'org.codehaus.groovy', name: 'groovy-test', version: groovyVersion testCompile "junit:junit:$junitVersion" testCompile (spockDependency) { + exclude group:'junit',module:'junit-dep' + exclude group:'org.codehaus.groovy',module:'groovy-all' + exclude group:'org.hamcrest',module:'hamcrest-core' transitive = false } } if (project.name == "grails-datastore-gorm-tck") { - compile spockDependency + compile spockDependency, { + exclude group:'junit',module:'junit-dep' + exclude group:'org.codehaus.groovy',module:'groovy-all' + exclude group:'org.hamcrest',module:'hamcrest-core' + transitive = false + } } } @@ -299,22 +306,22 @@ repositories.mavenDeployer { if(!isBuildSnapshot) { - beforeDeployment { MavenDeployment deployment -> - signing.signPom(deployment) + beforeDeployment { MavenDeployment deployment -> + signing.signPom(deployment) } } if(project.hasProperty("sonatypeUsername")) { - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: project.hasProperty("sonatypeUsername") ? project.sonatypeUsername : null, - password: project.hasProperty("sonatypePassword") ? project.sonatypePassword : null) + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: project.hasProperty("sonatypeUsername") ? project.sonatypeUsername : null, + password: project.hasProperty("sonatypePassword") ? project.sonatypePassword : null) } } if(project.hasProperty("artifactoryPublishUsername")) { snapshotRepository(url: "https://repo.grails.org/grails/libs-snapshots-local") { - authentication(userName: project.hasProperty("artifactoryPublishUsername") ? project.artifactoryPublishUsername : null, - password: project.hasProperty("artifactoryPublishPassword") ? project.artifactoryPublishPassword : null) - } + authentication(userName: project.hasProperty("artifactoryPublishUsername") ? project.artifactoryPublishUsername : null, + password: project.hasProperty("artifactoryPublishPassword") ? project.artifactoryPublishPassword : null) + } } pom.project {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d5c591c..0087cd3 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0a96f7c..eb9ac53 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@ -#Mon Apr 28 16:51:01 CEST 2014 +#Mon Dec 01 08:51:21 CST 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/grails-datastore-appengine/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-appengine/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index 725fbaf..0000000 --- a/grails-datastore-appengine/src/test/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,15 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Entity { -}
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.java index ce70c16..0810511 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.java
@@ -24,6 +24,7 @@ private boolean stateless = false; private boolean autoTimestamp = true; + private Object defaultSort = null; /** * @return Whether automatic time stamps should be applied to 'lastUpdate' and 'dateCreated' properties @@ -46,4 +47,15 @@ public void setStateless(boolean stateless) { this.stateless = stateless; } + + /** + * @return The default sort order definition, could be a string or a map + */ + public Object getSort() { + return defaultSort; + } + + public void setSort(Object defaultSort) { + this.defaultSort = defaultSort; + } }
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy similarity index 67% rename from grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.java rename to grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy index 20d6bee..3604c16 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy
@@ -1,4 +1,6 @@ -/* Copyright (C) 2011 SpringSource + +/* + * Copyright 2014 original authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,22 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.grails.datastore.mapping.config.utils; +package org.grails.datastore.mapping.config.utils -import java.util.Map; +import groovy.transform.CompileStatic +import org.grails.datastore.mapping.model.types.conversion.DefaultConversionService +import org.springframework.core.convert.ConversionService -import org.grails.datastore.mapping.model.types.conversion.DefaultConversionService; -import org.springframework.core.convert.ConversionService; /** - * Used to ease reading of configuration. + * @author Graeme Rocher + * @since 3.0 */ -public class ConfigUtils { - +@CompileStatic +class ConfigUtils { private static ConversionService conversionService = new DefaultConversionService(); public static <T> T read(Class<T> type, String key, Map<String, String> config, T defaultValue) { - String value = config.get(key); - return value == null ? defaultValue : conversionService.convert(value, type); + Object value = config.get(key); + return !value ? defaultValue : conversionService.convert(value, type); } }
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java index 1e33e7e..8523b50 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java
@@ -46,7 +46,7 @@ private static final Set<String> EXCLUDES = new HashSet(Arrays.asList("$getStaticMetaClass")); public boolean isProxy(Object object) { - return (object instanceof EntityProxy) || (object instanceof ProxyObject); + return object instanceof EntityProxy; } public Serializable getIdentifier(Object obj) {
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java index 447e5d2..bca9ec4 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java
@@ -61,7 +61,8 @@ protected Session session; protected boolean uniqueResult; protected Map<String, FetchType> fetchStrategies = new HashMap<String,FetchType>(); - protected boolean queryCache; + protected Boolean queryCache; + protected Boolean lockResult; protected Query(Session session, PersistentEntity entity) { this.entity = entity; @@ -113,7 +114,18 @@ * @return The query */ public Query cache(boolean cache) { - queryCache = true; + queryCache = cache; + return this; + } + + /** + * Specifies whether the query should obtain a pessimistic lock + * + * @param lock True if a lock should be obtained + * @return The query + */ + public Query lock(boolean lock) { + lockResult = lock; return this; } @@ -675,6 +687,7 @@ public static class Order { private Direction direction = Direction.ASC; private String property; + private boolean ignoreCase = false; public Order(String property) { this.property = property; @@ -685,22 +698,57 @@ this.property = property; } + /** + * Whether to ignore the case for this order definition + * + * @return This order instance + */ + public Order ignoreCase() { + this.ignoreCase = true; + return this; + } + + public boolean isIgnoreCase() { + return ignoreCase; + } + + /** + * @return The direction order by + */ public Direction getDirection() { return direction; } + /** + * @return The property name to order by + */ public String getProperty() { return property; } + /** + * Creates a new order for the given property in descending order + * + * @param property The property + * @return The order instance + */ public static Order desc(String property) { return new Order(property, Direction.DESC); } + /** + * Creates a new order for the given property in ascending order + * + * @param property The property + * @return The order instance + */ public static Order asc(String property) { return new Order(property, Direction.ASC); } + /** + * Represents the direction of the ordering + */ public static enum Direction { ASC, DESC }
diff --git a/grails-datastore-core/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-core/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index 725fbaf..0000000 --- a/grails-datastore-core/src/test/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,15 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Entity { -}
diff --git a/grails-datastore-dynamodb/build.gradle b/grails-datastore-dynamodb/build.gradle index 7d220a8..d5d5b9e 100644 --- a/grails-datastore-dynamodb/build.gradle +++ b/grails-datastore-dynamodb/build.gradle
@@ -1,4 +1,4 @@ -version = "0.1.2.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies { compile project(":grails-datastore-core")
diff --git a/grails-datastore-gemfire/build.gradle b/grails-datastore-gemfire/build.gradle index 7549d8e..8495583 100644 --- a/grails-datastore-gemfire/build.gradle +++ b/grails-datastore-gemfire/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" repositories { maven { url "http://dist.gemstone.com/maven/release" }
diff --git a/grails-datastore-gorm-cassandra/build.gradle b/grails-datastore-gorm-cassandra/build.gradle index 1169fba..0db05d6 100644 --- a/grails-datastore-gorm-cassandra/build.gradle +++ b/grails-datastore-gorm-cassandra/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails @@ -25,6 +25,7 @@ exclude group:'oro',module:'oro' exclude group:'asm',module:'asm' exclude group:'cglib',module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'xalan',module:'serializer' exclude group:'org.springframework',module:'spring-core' exclude group:'org.springframework',module:'spring-tx' @@ -59,7 +60,7 @@ testCompile project(':grails-datastore-gorm-test'), project(':grails-datastore-gorm-tck'), - ('cglib:cglib:2.2.2') + ('cglib:cglib-nodep:2.2.2')
diff --git a/grails-datastore-gorm-cassandra/src/main/groovy/org/codehaus/groovy/grails/compiler/GormToCassandraTransform.java b/grails-datastore-gorm-cassandra/src/main/groovy/org/codehaus/groovy/grails/compiler/GormToCassandraTransform.java index 57126ae..f38448a 100644 --- a/grails-datastore-gorm-cassandra/src/main/groovy/org/codehaus/groovy/grails/compiler/GormToCassandraTransform.java +++ b/grails-datastore-gorm-cassandra/src/main/groovy/org/codehaus/groovy/grails/compiler/GormToCassandraTransform.java
@@ -48,7 +48,7 @@ import org.codehaus.groovy.grails.commons.GrailsClassUtils; import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; import org.codehaus.groovy.grails.compiler.injection.AstTransformer; -import org.codehaus.groovy.grails.compiler.injection.GrailsASTUtils; +import org.grails.compiler.injection.GrailsASTUtils; import org.codehaus.groovy.grails.compiler.injection.GrailsArtefactClassInjector; import org.codehaus.groovy.grails.compiler.injection.GrailsDomainClassInjector; import org.codehaus.groovy.grails.io.support.GrailsResourceUtils;
diff --git a/grails-datastore-gorm-cassandra/src/main/groovy/org/grails/datastore/gorm/cassandra/bean/factory/CassandraMappingContextFactoryBean.groovy b/grails-datastore-gorm-cassandra/src/main/groovy/org/grails/datastore/gorm/cassandra/bean/factory/CassandraMappingContextFactoryBean.groovy index b62ebd3..941c8b9 100644 --- a/grails-datastore-gorm-cassandra/src/main/groovy/org/grails/datastore/gorm/cassandra/bean/factory/CassandraMappingContextFactoryBean.groovy +++ b/grails-datastore-gorm-cassandra/src/main/groovy/org/grails/datastore/gorm/cassandra/bean/factory/CassandraMappingContextFactoryBean.groovy
@@ -14,6 +14,7 @@ */ package org.grails.datastore.gorm.cassandra.bean.factory +import grails.core.GrailsDomainClass import groovy.transform.Canonical import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean
diff --git a/grails-datastore-gorm-cassandra/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy b/grails-datastore-gorm-cassandra/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy index 1ea34f2..85a2aad 100644 --- a/grails-datastore-gorm-cassandra/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-cassandra/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy
@@ -4,7 +4,7 @@ import javax.persistence.FlushModeType import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import grails.validation.ConstrainedProperty import org.grails.datastore.gorm.validation.constraints.UniqueConstraint import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity
diff --git a/grails-datastore-gorm-cassandra/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-gorm-cassandra/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index 596dd22..0000000 --- a/grails-datastore-gorm-cassandra/src/test/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,18 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@GroovyASTTransformationClass("org.codehaus.groovy.grails.compiler.injection.EntityASTTransformation") -public @interface Entity { -}
diff --git a/grails-datastore-gorm-cassandra/src/test/groovy/org/grails/datastore/gorm/cassandra/plugin/support/CassandraSpringConfigurerSpec.groovy b/grails-datastore-gorm-cassandra/src/test/groovy/org/grails/datastore/gorm/cassandra/plugin/support/CassandraSpringConfigurerSpec.groovy index 86adb93..706a4b7 100644 --- a/grails-datastore-gorm-cassandra/src/test/groovy/org/grails/datastore/gorm/cassandra/plugin/support/CassandraSpringConfigurerSpec.groovy +++ b/grails-datastore-gorm-cassandra/src/test/groovy/org/grails/datastore/gorm/cassandra/plugin/support/CassandraSpringConfigurerSpec.groovy
@@ -1,12 +1,12 @@ package org.grails.datastore.gorm.cassandra.plugin.support +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication import grails.gorm.tests.Person +import grails.plugins.DefaultGrailsPluginManager import grails.spring.BeanBuilder -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.plugins.DefaultGrailsPluginManager +import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.datastore.gorm.Setup import org.grails.datastore.mapping.cassandra.CassandraDatastore import org.grails.datastore.mapping.cassandra.config.CassandraMappingContext @@ -16,6 +16,8 @@ import com.datastax.driver.core.KeyspaceMetadata + + /** */ class CassandraSpringConfigurerSpec extends Specification{
diff --git a/grails-datastore-gorm-dynamodb/build.gradle b/grails-datastore-gorm-dynamodb/build.gradle index fbf2455..05d1ef0 100644 --- a/grails-datastore-gorm-dynamodb/build.gradle +++ b/grails-datastore-gorm-dynamodb/build.gradle
@@ -1,4 +1,4 @@ -version = "0.1.2.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails
diff --git a/grails-datastore-gorm-gemfire/build.gradle b/grails-datastore-gorm-gemfire/build.gradle index 4734a8f..b39fd97 100644 --- a/grails-datastore-gorm-gemfire/build.gradle +++ b/grails-datastore-gorm-gemfire/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" repositories { maven { url "http://dist.gemstone.com/maven/release" }
diff --git a/grails-datastore-gorm-hibernate-core/build.gradle b/grails-datastore-gorm-hibernate-core/build.gradle index 33f3233..df69fc02 100644 --- a/grails-datastore-gorm-hibernate-core/build.gradle +++ b/grails-datastore-gorm-hibernate-core/build.gradle
@@ -17,6 +17,7 @@ exclude group:'oro',module:'oro' exclude group:'asm',module:'asm' exclude group:'cglib',module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'xalan',module:'serializer' exclude group:'org.springframework',module:'spring-core' exclude group:'org.springframework',module:'spring-tx'
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractEventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractEventTriggeringInterceptor.java index 788b1db..8e47180 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractEventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractEventTriggeringInterceptor.java
@@ -20,15 +20,15 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; import org.codehaus.groovy.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping; import org.codehaus.groovy.grails.orm.hibernate.support.SoftKey; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateDomainClass.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateDomainClass.java index e4a47cd..19923a0 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateDomainClass.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateDomainClass.java
@@ -22,15 +22,15 @@ import java.util.Map; import java.util.Set; -import org.codehaus.groovy.grails.commons.AbstractGrailsClass; -import org.codehaus.groovy.grails.commons.ExternalGrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.exceptions.InvalidPropertyException; -import org.codehaus.groovy.grails.validation.ConstraintsEvaluator; -import org.codehaus.groovy.grails.validation.DefaultConstraintEvaluator; -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.util.GrailsClassUtils; +import grails.validation.ConstraintsEvaluator; +import org.grails.core.AbstractGrailsClass; +import org.grails.core.exceptions.InvalidPropertyException; +import org.grails.validation.DefaultConstraintEvaluator; +import org.grails.validation.GrailsDomainClassValidator; import org.hibernate.SessionFactory; import org.hibernate.metadata.ClassMetadata; import org.hibernate.type.AnyType; @@ -42,7 +42,7 @@ import org.springframework.validation.Validator; @SuppressWarnings("rawtypes") -public abstract class AbstractGrailsHibernateDomainClass extends AbstractGrailsClass implements ExternalGrailsDomainClass { +public abstract class AbstractGrailsHibernateDomainClass extends AbstractGrailsClass implements GrailsDomainClass { public static final String HIBERNATE = "hibernate"; @@ -103,7 +103,7 @@ if (!propertyName.equals(ident) && !(versionPropertyName != null && propertyName.equals(versionPropertyName))) { - PropertyDescriptor pd = GrailsClassUtils.getProperty(clazz,propertyName); + PropertyDescriptor pd = GrailsClassUtils.getProperty(clazz, propertyName); if (pd == null) continue; GrailsHibernateDomainClassProperty prop = new GrailsHibernateDomainClassProperty(this, propertyName);
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateDatastore.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateDatastore.java index d775360..b028009 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateDatastore.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateDatastore.java
@@ -14,6 +14,7 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.config.Config; import groovy.util.ConfigObject; import org.grails.datastore.mapping.core.AbstractDatastore; @@ -31,10 +32,10 @@ public abstract class AbstractHibernateDatastore extends AbstractDatastore implements ApplicationContextAware { protected SessionFactory sessionFactory; - protected ConfigObject config; + protected Config config; protected AbstractEventTriggeringInterceptor eventTriggeringInterceptor; - protected AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { + protected AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config, ApplicationContext applicationContext) { super(mappingContext); this.sessionFactory = sessionFactory; this.config = config; @@ -44,7 +45,7 @@ } } - public AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { + public AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config) { this(mappingContext, sessionFactory, config, null); }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormEnhancer.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormEnhancer.groovy index 7ef8c9b..e9071a5b 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormEnhancer.groovy +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormEnhancer.groovy
@@ -14,11 +14,15 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.util.GrailsClassUtils import grails.util.GrailsNameUtils import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode -import org.codehaus.groovy.grails.commons.* import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateNamedQueriesBuilder +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.core.support.GrailsDomainConfigurationUtil import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.model.PersistentEntity @@ -46,6 +50,14 @@ } @Override + void enhance(PersistentEntity e, boolean onlyExtendedMethods) { + super.enhance(e, onlyExtendedMethods) + + GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, e.name) + datastore.mappingContext.addEntityValidator(e, domainClass.validator) + } + + @Override protected void registerConstraints(Datastore datastore) { // no-op }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy index 2c9b4c3..76e2b3d 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy
@@ -15,31 +15,471 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClassProperty +import grails.core.support.proxy.ProxyHandler +import grails.util.GrailsClassUtils +import grails.validation.CascadingValidator +import grails.validation.DeferredBindingActions +import grails.validation.ValidationException +import groovy.transform.CompileDynamic import groovy.transform.CompileStatic - +import org.codehaus.groovy.grails.orm.hibernate.proxy.SimpleHibernateProxyHandler +import org.codehaus.groovy.grails.orm.hibernate.support.HibernateRuntimeUtils +import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint +import org.grails.core.lifecycle.ShutdownOperations import org.grails.datastore.gorm.GormInstanceApi -import org.hibernate.SessionFactory +import org.grails.datastore.mapping.engine.event.ValidationEvent +import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.datastore.mapping.model.PersistentProperty +import org.grails.datastore.mapping.model.types.Association +import org.grails.datastore.mapping.model.types.ToOne +import org.hibernate.* +import org.springframework.beans.BeanWrapperImpl +import org.springframework.beans.InvalidPropertyException +import org.springframework.dao.DataAccessException +import org.springframework.validation.Errors +import org.springframework.validation.Validator + +/** + * Abstract extension of the {@link GormInstanceApi} class that provides common logic shared by Hibernate 3 and Hibernate 4 + * + * @author Graeme Rocher + * @param < D > + */ @CompileStatic -class AbstractHibernateGormInstanceApi<D> extends GormInstanceApi<D> { +abstract class AbstractHibernateGormInstanceApi<D> extends GormInstanceApi<D> { + private static final String ARGUMENT_VALIDATE = "validate"; + private static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; + private static final String ARGUMENT_FLUSH = "flush"; + private static final String ARGUMENT_INSERT = "insert"; + private static final String ARGUMENT_MERGE = "merge"; + private static final String ARGUMENT_FAIL_ON_ERROR = "failOnError"; + protected static final Object[] EMPTY_ARRAY = [] + /** + * When a domain instance is saved without validation, we put it + * into this thread local variable. Any code that needs to know + * whether the domain instance should be validated can just check + * the value. Note that this only works because the session is + * flushed when a domain instance is saved without validation. + */ + static ThreadLocal<Set<Integer>> disableAutoValidationForThreadLocal = new ThreadLocal<Set<Integer>>() + static final ThreadLocal<Boolean> insertActiveThreadLocal = new ThreadLocal<Boolean>() + + static { + ShutdownOperations.addOperation(new Runnable() { + public void run() { + AbstractHibernateGormInstanceApi.disableAutoValidationForThreadLocal.remove() + AbstractHibernateGormInstanceApi.insertActiveThreadLocal.remove() + } + }); + } + + private static Set<Integer> getDisableAutoValidationFor() { + Set<Integer> identifiers = AbstractHibernateGormInstanceApi.disableAutoValidationForThreadLocal.get() + if (identifiers == null) + AbstractHibernateGormInstanceApi.disableAutoValidationForThreadLocal.set(identifiers = new HashSet<Integer>()) + return identifiers; + } + + public static boolean isAutoValidationDisabled(Object obj) { + Set<Integer> identifiers = getDisableAutoValidationFor() + return obj != null && identifiers.contains(System.identityHashCode(obj)) + } + + public static void clearDisabledValidations(Object obj) { + getDisableAutoValidationFor().remove(System.identityHashCode(obj)) + } + + public static void clearDisabledValidations() { + getDisableAutoValidationFor().clear(); + } protected SessionFactory sessionFactory protected ClassLoader classLoader - protected boolean cacheQueriesByDefault = false - + protected IHibernateTemplate hibernateTemplate + protected ProxyHandler proxyHandler = new SimpleHibernateProxyHandler() Map config = Collections.emptyMap() - protected AbstractHibernateGormInstanceApi(Class<D> persistentClass, AbstractHibernateDatastore datastore, ClassLoader classLoader) { + protected AbstractHibernateGormInstanceApi(Class<D> persistentClass, AbstractHibernateDatastore datastore, ClassLoader classLoader, IHibernateTemplate hibernateTemplate) { super(persistentClass, datastore) this.classLoader = classLoader sessionFactory = datastore.getSessionFactory() + this.hibernateTemplate = hibernateTemplate } - protected boolean shouldFlush(Map map = [:]) { - if (map?.containsKey('flush')) { - return Boolean.TRUE == map.flush + + + @Override + D save(D target, Map arguments) { + + PersistentEntity domainClass = persistentEntity + DeferredBindingActions.runActions() + boolean shouldFlush = shouldFlush(arguments) + boolean shouldValidate = shouldValidate(arguments, persistentEntity) + + HibernateRuntimeUtils.autoAssociateBidirectionalOneToOnes(domainClass, target) + + if (shouldValidate) { + Validator validator = datastore.mappingContext.getEntityValidator(domainClass) + + Errors errors = HibernateRuntimeUtils.setupErrorsProperty(target) + + if (validator) { + datastore.applicationContext?.publishEvent new ValidationEvent(datastore, target) + + boolean deepValidate = true + if (arguments?.containsKey(ARGUMENT_DEEP_VALIDATE)) { + deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments); + } + + AbstractPersistentConstraint.sessionFactory.set(sessionFactory) + try { + if (deepValidate && (validator instanceof CascadingValidator)) { + ((CascadingValidator)validator).validate target, errors, deepValidate + } + else { + validator.validate target, errors + } + } + finally { + AbstractPersistentConstraint.sessionFactory.remove() + } + + if (errors.hasErrors()) { + handleValidationError(domainClass,target,errors); + if (shouldFail(arguments)) { + throw new ValidationException("Validation Error(s) occurred during save()", errors) + } + return null + } + + setObjectToReadWrite(target); + } + } + + // this piece of code will retrieve a persistent instant + // of a domain class property is only the id is set thus + // relieving this burden off the developer + autoRetrieveAssocations domainClass, target + + if (!shouldValidate) { + Set<Integer> identifiers = getDisableAutoValidationFor() + identifiers.add System.identityHashCode(target) + } + + if (shouldInsert(arguments)) { + return performInsert(target, shouldFlush) + } + else if(shouldMerge(arguments)) { + return performMerge(target, shouldFlush) + } + else { + return performSave(target, shouldFlush) + } + } + + @Override + D merge(D instance, Map params) { + Map args = new HashMap(params) + args[ARGUMENT_MERGE] = true + return save(instance, params) + } + + @Override + D insert(D instance, Map params) { + Map args = new HashMap(params) + args[ARGUMENT_INSERT] = true + return save(instance, args) + } + + @Override + void discard(D instance) { + hibernateTemplate.evict instance + } + + @Override + void delete(D instance, Map params = Collections.emptyMap()) { + boolean flush = shouldFlush(params) + try { + hibernateTemplate.execute { Session session -> + session.delete instance + if(flush) { + session.flush() + } + } + } + catch (DataAccessException e) { + try { + hibernateTemplate.execute { Session session -> + session.flushMode = FlushMode.MANUAL + } + } + finally { + throw e + } + } + } + + @Override + boolean isAttached(D instance) { + hibernateTemplate.contains instance + } + + @Override + boolean instanceOf(D instance, Class cls) { + return proxyHandler.unwrapIfProxy(instance) in cls + } + + @Override + D lock(D instance) { + hibernateTemplate.lock(instance, LockMode.PESSIMISTIC_WRITE) + } + + @Override + D attach(D instance) { + hibernateTemplate.lock(instance, LockMode.NONE) + return instance + } + + @Override + D refresh(D instance) { + hibernateTemplate.refresh(instance) + return instance + } + + protected D performSave(final D target, final boolean flush) { + hibernateTemplate.execute { Session session -> + session.saveOrUpdate target + if (flush) { + flushSession session + } + return target + } + } + + protected D performMerge(final D target, final boolean flush) { + hibernateTemplate.execute { Session session -> + Object merged = session.merge(target) + session.lock(merged, LockMode.NONE); + if (flush) { + flushSession session + } + return merged + } + } + + protected D performInsert(final D target, final boolean shouldFlush) { + hibernateTemplate.execute { Session session -> + try { + markInsertActive() + session.save target + if (shouldFlush) { + flushSession session + } + return target + } finally { + resetInsertActive() + } + + } + } + + protected void flushSession(Session session) throws HibernateException { + try { + session.flush() + } catch (HibernateException e) { + // session should not be flushed again after a data acccess exception! + session.setFlushMode FlushMode.MANUAL + throw e + } + } + /** + * Performs automatic association retrieval + * @param entity The domain class to retrieve associations for + * @param target The target object + */ + @SuppressWarnings("unchecked") + private void autoRetrieveAssocations(PersistentEntity entity, Object target) { + def bean = new BeanWrapperImpl(target) + IHibernateTemplate t = this.hibernateTemplate + for (PersistentProperty prop in entity.associations) { + if(prop instanceof ToOne) { + ToOne toOne = (ToOne)prop + def propValue = bean.getPropertyValue(prop.name) + if (propValue == null || t.contains(propValue)) { + continue + } + + PersistentEntity otherSide = toOne.associatedEntity + if (otherSide == null) { + continue + } + + def propBean = new BeanWrapperImpl(propValue) + try { + def id = (Serializable)propBean.getPropertyValue(otherSide.identity.name); + if (id) { + final Object propVal = t.get(prop.type, id) + if (propVal) { + bean.setPropertyValue prop.name, propVal + } + } + } + catch (InvalidPropertyException ipe) { + // property is not accessable + } + } + + } + } + + /** + * Checks whether validation should be performed + * @return true if the domain class should be validated + * @param arguments The arguments to the validate method + * @param domainClass The domain class + */ + private boolean shouldValidate(Map arguments, PersistentEntity entity) { + if (!entity) { + return false + } + + if (arguments.containsKey(ARGUMENT_VALIDATE)) { + return GrailsClassUtils.getBooleanFromMap(ARGUMENT_VALIDATE, arguments) + } + return true + } + + private boolean shouldInsert(Map arguments) { + GrailsClassUtils.getBooleanFromMap(ARGUMENT_INSERT, arguments) + } + + private boolean shouldMerge(Map arguments) { + GrailsClassUtils.getBooleanFromMap(ARGUMENT_MERGE, arguments) + } + + + protected boolean shouldFlush(Map map) { + if (map?.containsKey(ARGUMENT_FLUSH)) { + return GrailsClassUtils.getBooleanFromMap(ARGUMENT_FLUSH, map) } return config?.autoFlush instanceof Boolean ? config.autoFlush : false } + + protected boolean shouldFail(Map map) { + if (map?.containsKey(ARGUMENT_FAIL_ON_ERROR)) { + return GrailsClassUtils.getBooleanFromMap(ARGUMENT_FAIL_ON_ERROR, map) + } + return config?.get(ARGUMENT_FAIL_ON_ERROR) instanceof Boolean ? GrailsClassUtils.getBooleanFromMap(ARGUMENT_FAIL_ON_ERROR, config) : false + } + + /** + * Sets the flush mode to manual. which ensures that the database changes are not persisted to the database + * if a validation error occurs. If save() is called again and validation passes the code will check if there + * is a manual flush mode and flush manually if necessary + * + * @param domainClass The domain class + * @param target The target object that failed validation + * @param errors The Errors instance @return This method will return null signaling a validation failure + */ + protected Object handleValidationError(PersistentEntity entity, final Object target, Errors errors) { + // if a validation error occurs set the object to read-only to prevent a flush + setObjectToReadOnly target + if (entity) { + for (Association association in entity.associations) { + if (association instanceof ToOne) { + if(proxyHandler.isInitialized(target, association.name)) { + def bean = new BeanWrapperImpl(target) + def propertyValue = bean.getPropertyValue(association.name) + if (propertyValue != null) { + setObjectToReadOnly propertyValue + } + } + } + } + } + setErrorsOnInstance target, errors + return null + } + + /** + * Sets the target object to read-only using the given SessionFactory instance. This + * avoids Hibernate performing any dirty checking on the object + * + * + * @param target The target object + * @param sessionFactory The SessionFactory instance + */ + public void setObjectToReadOnly(Object target) { + hibernateTemplate.execute { Session session -> + if (session.contains(target) && proxyHandler.isInitialized(target)) { + target = proxyHandler.unwrapIfProxy(target) + session.setReadOnly target, true + session.flushMode = FlushMode.MANUAL + } + } + } + /** + * Sets the target object to read-write, allowing Hibernate to dirty check it and auto-flush changes. + * + * @see #setObjectToReadOnly(Object) + * + * @param target The target object + * @param sessionFactory The SessionFactory instance + */ + public abstract void setObjectToReadWrite(Object target) + + /** + * Associates the Errors object on the instance + * + * @param target The target instance + * @param errors The Errors object + */ + @CompileDynamic + protected void setErrorsOnInstance(Object target, Errors errors) { + target."$GrailsDomainClassProperty.ERRORS" = errors + } + + /** + * Prevents hitting the database for an extra check if the row exists in the database. + * + * ThreadLocal is used to pass the "insert:true" information to Hibernate. + * + * @see org.hibernate.event.def.AbstractSaveEventListener#getAssumedUnsaved() + */ + public static Boolean getAssumedUnsaved() { + return insertActiveThreadLocal.get(); + } + + /** + * Called by org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod's performInsert + * to set a ThreadLocal variable that determines the value for getAssumedUnsaved(). + */ + public static void markInsertActive() { + insertActiveThreadLocal.set(Boolean.TRUE); + } + + /** + * Clears the ThreadLocal variable set by markInsertActive(). + */ + public static void resetInsertActive() { + insertActiveThreadLocal.remove(); + } + + /** + * Increments the entities version number in order to force an update + * @param target The target entity + */ + @CompileDynamic + protected void incrementVersion(Object target) { + if (target.hasProperty(GrailsDomainClassProperty.VERSION)) { + Object version = target."${GrailsDomainClassProperty.VERSION}" + if (version instanceof Long) { + target."${GrailsDomainClassProperty.VERSION}" = ++((Long)version) + } + } + } + }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy new file mode 100644 index 0000000..806e83e --- /dev/null +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy
@@ -0,0 +1,491 @@ +package org.codehaus.groovy.grails.orm.hibernate + +import grails.core.support.proxy.ProxyHandler +import grails.util.GrailsClassUtils +import groovy.transform.CompileStatic +import org.codehaus.groovy.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder +import org.codehaus.groovy.grails.orm.hibernate.cfg.CompositeIdentity +import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException +import org.codehaus.groovy.grails.orm.hibernate.proxy.SimpleHibernateProxyHandler +import org.codehaus.groovy.grails.orm.hibernate.query.GrailsHibernateQueryUtils +import org.codehaus.groovy.grails.orm.hibernate.support.HibernateRuntimeUtils +import org.grails.datastore.gorm.GormStaticApi +import org.grails.datastore.gorm.finders.DynamicFinder +import org.grails.datastore.gorm.finders.FinderMethod +import org.grails.datastore.mapping.core.Datastore +import org.hibernate.Criteria +import org.hibernate.FlushMode +import org.hibernate.Query +import org.hibernate.Session +import org.hibernate.criterion.Example +import org.hibernate.criterion.Projections +import org.hibernate.criterion.Restrictions +import org.hibernate.transform.DistinctRootEntityResultTransformer +import org.springframework.core.convert.ConversionService +import org.springframework.transaction.PlatformTransactionManager + +import java.util.regex.Pattern + +/** + * Abstract implementation of the Hibernate static API for GORM, providing String-based method implementations + * + * @author Graeme Rocher + * @since 4.0 + */ +@CompileStatic +abstract class AbstractHibernateGormStaticApi<D> extends GormStaticApi<D> { + + protected ProxyHandler proxyHandler = new SimpleHibernateProxyHandler() + protected Pattern queryPattern + protected IHibernateTemplate hibernateTemplate + protected ConversionService conversionService + + AbstractHibernateGormStaticApi(Class<D> persistentClass, Datastore datastore, List<FinderMethod> finders, IHibernateTemplate hibernateTemplate) { + this(persistentClass, datastore, finders, null, hibernateTemplate) + } + + AbstractHibernateGormStaticApi(Class<D> persistentClass, Datastore datastore, List<FinderMethod> finders, PlatformTransactionManager transactionManager, IHibernateTemplate hibernateTemplate) { + super(persistentClass, datastore, finders, transactionManager) + this.hibernateTemplate = hibernateTemplate + this.queryPattern = ~/(?i)from(?-i)\s+[${persistentEntity.name}|${persistentEntity.javaClass.simpleName}].*/ + this.conversionService = datastore.mappingContext.conversionService + } + + @Override + D get(Serializable id) { + if (id || (id instanceof Number)) { + id = convertIdentifier(id) + D result = (D)hibernateTemplate.get((Class)persistentClass, id) + return (D)proxyHandler.unwrapIfProxy(result) + } + } + + @Override + D read(Serializable id) { + if (id == null) { + return null + } + + hibernateTemplate.execute( { Session session -> + + def criteria = session.createCriteria(persistentEntity.javaClass) + criteria.add Restrictions.idEq(convertIdentifier(id)) + criteria.readOnly = true + def result = (D) criteria.uniqueResult() + if(result) + session.setReadOnly(result, true) + return proxyHandler.unwrapIfProxy( result ) + } ) + } + + @Override + D load(Serializable id) { + id = convertIdentifier(id) + if (id != null) { + return (D) hibernateTemplate.load((Class)persistentClass, id) + } + } + + @Override + List<D> getAll() { + (List<D>)hibernateTemplate.execute({ Session session -> + Criteria criteria = session.createCriteria(persistentClass) + hibernateTemplate.applySettings(criteria) + criteria.list() + }) + } + + @Override + Integer count() { + (Integer)hibernateTemplate.execute({ Session session -> + def criteria = session.createCriteria(persistentClass) + hibernateTemplate.applySettings(criteria) + criteria.setProjection(Projections.rowCount()) + def num = criteria.uniqueResult() + num == null ? 0 : num + }) + } + + @Override + boolean exists(Serializable id) { + id = convertIdentifier(id) + hibernateTemplate.execute { Session session -> + Criteria criteria = session.createCriteria(persistentEntity.javaClass) + hibernateTemplate.applySettings(criteria) + criteria.add(Restrictions.idEq(id)) + .setProjection(Projections.rowCount()) + .uniqueResult() + } + } + + D first(Map m) { + def entityMapping = AbstractGrailsDomainBinder.getMapping(persistentEntity.javaClass) + if (entityMapping?.identity instanceof CompositeIdentity) { + throw new UnsupportedOperationException('The first() method is not supported for domain classes that have composite keys.') + } + super.first(m) + } + + D last(Map m) { + def entityMapping = AbstractGrailsDomainBinder.getMapping(persistentEntity.javaClass) + if (entityMapping?.identity instanceof CompositeIdentity) { + throw new UnsupportedOperationException('The last() method is not supported for domain classes that have composite keys.') + } + super.last(m) + } + + /** + * Implements the 'find(String' method to use HQL queries with named arguments + * + * @param query The query + * @param queryNamedArgs The named arguments + * @param args Any additional query arguments + * @return A result or null if no result found + */ + @Override + D find(String query, Map queryNamedArgs, Map args) { + if (!queryPattern.matcher(query).matches()) { + throw new GrailsQueryException("Invalid query [$query] for domain class [$persistentEntity.name]"); + } + + def template = hibernateTemplate + queryNamedArgs = new HashMap(queryNamedArgs) + args = new HashMap(args) + return (D) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + populateQueryArguments(q, queryNamedArgs) + populateQueryArguments(q, args) + populateQueryWithNamedArguments(q, queryNamedArgs) + return executeHibernateQuery(q, args) + } + } + + @Override + D find(String query, Collection params, Map args) { + if (!queryPattern.matcher(query).matches()) { + throw new GrailsQueryException("Invalid query [$query] for domain class [$persistentEntity.name]"); + } + + args = new HashMap(args) + def template = hibernateTemplate + return (D) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + params.eachWithIndex { val, int i -> + if (val instanceof CharSequence) { + q.setParameter i, val.toString() + } + else { + q.setParameter i, val + } + } + populateQueryArguments(q, args) + return executeHibernateQuery(q, args) + } + } + + @Override + List<D> findAll(String query, Map params, Map args) { + if (!queryPattern.matcher(query).matches()) { + throw new GrailsQueryException("Invalid query [$query] for domain class [$persistentEntity.name]"); + } + + args = new HashMap(args) + params = new HashMap(params) + def template = hibernateTemplate + return (List<D>) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + populateQueryArguments(q, params) + populateQueryArguments(q, args) + populateQueryWithNamedArguments(q, params) + + return q.list() + } + } + + @Override + List<D> findAll(String query, Collection params, Map args) { + if (!queryPattern.matcher(query).matches()) { + throw new GrailsQueryException("Invalid query [$query] for domain class [$persistentEntity.name]"); + } + + args = new HashMap(args) + + def template = hibernateTemplate + return (List<D>) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + params.eachWithIndex { val, int i -> + if (val instanceof CharSequence) { + q.setParameter i, val.toString() + } + else { + q.setParameter i, val + } + } + populateQueryArguments(q, args) + return q.list() + } + } + + @Override + D find(D exampleObject, Map args) { + def template = hibernateTemplate + return (D) template.execute { Session session -> + Example example = Example.create(exampleObject).ignoreCase() + + Criteria crit = session.createCriteria(persistentEntity.javaClass); + hibernateTemplate.applySettings(crit) + crit.add example + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) + crit.maxResults = 1 + List results = crit.list() + if (results) { + return proxyHandler.unwrapIfProxy( results.get(0) ) + } + } + } + + @Override + List<D> findAll(D exampleObject, Map args) { + def template = hibernateTemplate + return (List<D>) template.execute { Session session -> + Example example = Example.create(exampleObject).ignoreCase() + + Criteria crit = session.createCriteria(persistentEntity.javaClass); + hibernateTemplate.applySettings(crit) + crit.add example + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) + crit.list() + } + } + + @Override + List<D> findAllWhere(Map queryMap, Map args) { + if (!queryMap) return null + (List<D>)hibernateTemplate.execute { Session session -> + Map<String, Object> processedQueryMap = [:] + queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + Map queryArgs = filterQueryArgumentMap(processedQueryMap) + List<String> nullNames = removeNullNames(queryArgs) + Criteria criteria = session.createCriteria(persistentClass) + hibernateTemplate.applySettings(criteria) + criteria.add(Restrictions.allEq(queryArgs)) + for (name in nullNames) { + criteria.add Restrictions.isNull(name) + } + criteria.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE) + criteria.list() + } + } + + @Override + List<D> executeQuery(String query, Map params, Map args) { + def template = hibernateTemplate + args = new HashMap(args) + params = new HashMap(params) + + return (List<D>) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + populateQueryArguments(q, params) + populateQueryArguments(q, args) + populateQueryWithNamedArguments(q, params) + + return q.list() + } + } + + @Override + List<D> executeQuery(String query, Collection params, Map args) { + def template = hibernateTemplate + args = new HashMap(args) + + return (List<D>) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + + params.eachWithIndex { val, int i -> + if (val instanceof CharSequence) { + q.setParameter i, val.toString() + } + else { + q.setParameter i, val + } + } + populateQueryArguments(q, args) + return q.list() + } + } + + @Override + D findWhere(Map queryMap, Map args) { + if (!queryMap) return null + (D)hibernateTemplate.execute { Session session -> + Map<String, Object> processedQueryMap = [:] + queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + Map queryArgs = filterQueryArgumentMap(processedQueryMap) + List<String> nullNames = removeNullNames(queryArgs) + Criteria criteria = session.createCriteria(persistentClass) + hibernateTemplate.applySettings(criteria) + criteria.add(Restrictions.allEq(queryArgs)) + for (name in nullNames) { + criteria.add Restrictions.isNull(name) + } + criteria.setMaxResults(1) + proxyHandler.unwrapIfProxy(criteria.uniqueResult()) + } + } + + + + List<D> getAll(List ids) { + getAllInternal(ids) + } + + List<D> getAll(Long... ids) { + getAllInternal(ids as List) + } + + @Override + List<D> getAll(Serializable... ids) { + getAllInternal(ids as List) + } + + private List getAllInternal(List ids) { + if (!ids) return [] + + (List)hibernateTemplate.execute { Session session -> + def identityType = persistentEntity.identity.type + ids = ids.collect { HibernateRuntimeUtils.convertValueToType((Serializable)it, identityType, conversionService) } + def criteria = session.createCriteria(persistentClass) + hibernateTemplate.applySettings(criteria) + def identityName = persistentEntity.identity.name + criteria.add(Restrictions.'in'(identityName, ids)) + def results = criteria.list() + def idsMap = [:] + for (object in results) { + idsMap[object[identityName]] = object + } + results.clear() + for (id in ids) { + results << idsMap[id] + } + results + } + } + + protected Map filterQueryArgumentMap(Map query) { + def queryArgs = [:] + for (entry in query.entrySet()) { + if (entry.value instanceof CharSequence) { + queryArgs[entry.key] = entry.value.toString() + } + else { + queryArgs[entry.key] = entry.value + } + } + return queryArgs + } + + + protected List<String> removeNullNames(Map query) { + List<String> nullNames = [] + Set<String> allNames = new HashSet(query.keySet()) + for (String name in allNames) { + if (query[name] == null) { + query.remove name + nullNames << name + } + } + nullNames + } + + protected D executeHibernateQuery(Query q, Map args) { + q.maxResults = 1 + List results = q.list() + if (results) { + return (D)proxyHandler.unwrapIfProxy(results.get(0)) + } + } + + protected Serializable convertIdentifier(Serializable id) { + (Serializable)HibernateRuntimeUtils.convertValueToType(id, persistentEntity.identity.type, conversionService) + } + + protected void populateQueryWithNamedArguments(Query q, Map queryNamedArgs) { + + if (queryNamedArgs) { + for (Map.Entry entry in queryNamedArgs.entrySet()) { + def key = entry.key + if (!(key instanceof CharSequence)) { + throw new GrailsQueryException("Named parameter's name must be String: $queryNamedArgs") + } + String stringKey = key.toString() + def value = entry.value + + if(value == null) { + q.setParameter stringKey, null + } else if (value instanceof CharSequence) { + q.setParameter stringKey, value.toString() + } else if (List.class.isAssignableFrom(value.getClass())) { + q.setParameterList stringKey, (List) value + } else if (value.getClass().isArray()) { + q.setParameterList stringKey, (Object[]) value + } else { + q.setParameter stringKey, value + } + } + } + } + + protected Integer intValue(Map args, String key) { + def value = args.get(key) + if(value) { + return conversionService.convert(value, Integer.class) + } + return null + } + + protected void populateQueryArguments(Query q, Map args) { + Integer max = intValue(args, DynamicFinder.ARGUMENT_MAX) + args.remove(DynamicFinder.ARGUMENT_MAX) + Integer offset = intValue(args, DynamicFinder.ARGUMENT_OFFSET) + args.remove(DynamicFinder.ARGUMENT_OFFSET) + + // + if (max != null) { + q.maxResults = max + } + if (offset != null) { + q.firstResult = offset + } + + if (args.containsKey(DynamicFinder.ARGUMENT_CACHE)) { + q.cacheable = GrailsClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_CACHE, args) + } + if (args.containsKey(DynamicFinder.ARGUMENT_FETCH_SIZE)) { + Integer fetchSizeParam = conversionService.convert(args.remove(DynamicFinder.ARGUMENT_FETCH_SIZE), Integer.class); + q.setFetchSize(fetchSizeParam.intValue()); + } + if (args.containsKey(DynamicFinder.ARGUMENT_TIMEOUT)) { + Integer timeoutParam = conversionService.convert(args.remove(DynamicFinder.ARGUMENT_TIMEOUT), Integer.class); + q.setTimeout(timeoutParam.intValue()); + } + if (args.containsKey(DynamicFinder.ARGUMENT_READ_ONLY)) { + q.setReadOnly((Boolean)args.remove(DynamicFinder.ARGUMENT_READ_ONLY)); + } + if (args.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { + q.setFlushMode((FlushMode)args.remove(DynamicFinder.ARGUMENT_FLUSH_MODE)); + } + + args.remove(DynamicFinder.ARGUMENT_CACHE) + } +}
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy index 06e8720..cbc9fae 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy
@@ -15,55 +15,137 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClassProperty +import grails.util.GrailsClassUtils +import grails.validation.CascadingValidator +import grails.validation.ValidationErrors import groovy.transform.CompileStatic - +import org.codehaus.groovy.grails.orm.hibernate.support.HibernateRuntimeUtils +import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint import org.grails.datastore.gorm.GormValidationApi -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.metaclass.DynamicMethodInvocation -import org.grails.datastore.gorm.GormValidationApi +import org.grails.datastore.mapping.engine.event.ValidationEvent +import org.springframework.validation.Errors +import org.springframework.validation.FieldError +import org.springframework.validation.ObjectError @CompileStatic abstract class AbstractHibernateGormValidationApi<D> extends GormValidationApi<D> { + public static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; + private static final String ARGUMENT_EVICT = "evict"; + + protected ClassLoader classLoader + protected AbstractHibernateDatastore datastore + protected IHibernateTemplate hibernateTemplate protected AbstractHibernateGormValidationApi(Class<D> persistentClass, AbstractHibernateDatastore datastore, ClassLoader classLoader) { super(persistentClass, datastore) this.classLoader = classLoader + this.datastore = datastore } - protected abstract DynamicMethodInvocation getValidateMethod() @Override - boolean validate(D instance) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [] as Object[]) - } - return super.validate(instance) + boolean validate(D instance, Map arguments = Collections.emptyMap()) { + validate(instance, null, arguments) } - @Override - boolean validate(D instance, boolean evict) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [evict] as Object[]) + boolean validate(D instance, List validatedFieldsList, Map arguments = Collections.emptyMap()) { + Errors errors = setupErrorsProperty(instance); + if(validator == null) return true + + Boolean valid = Boolean.TRUE + // should evict? + boolean evict = false + boolean deepValidate = true + Set validatedFields = null + if(validatedFieldsList != null) { + validatedFields = new HashSet(validatedFieldsList) } - return super.validate(instance, evict) + + if (arguments.containsKey(ARGUMENT_DEEP_VALIDATE)) { + deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments) + } + + evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, arguments); + + fireEvent instance, validatedFieldsList + + AbstractPersistentConstraint.sessionFactory.set datastore.sessionFactory + try { + if (deepValidate && (validator instanceof CascadingValidator)) { + ((CascadingValidator)validator).validate instance, errors, deepValidate + } + else { + validator.validate instance, errors + } + } + finally { + AbstractPersistentConstraint.sessionFactory.remove() + } + + int oldErrorCount = errors.errorCount + errors = filterErrors(errors, validatedFields, instance) + + if (errors.hasErrors()) { + valid = Boolean.FALSE + if (evict) { + // if an boolean argument 'true' is passed to the method + // and validation fails then the object will be evicted + // from the session, ensuring it is not saved later when + // flush is called + if (hibernateTemplate.contains(instance)) { + hibernateTemplate.evict(instance) + } + } + } + + // If the errors have been filtered, update the 'errors' object attached to the target. + if (errors.errorCount != oldErrorCount) { + MetaClass metaClass = GroovySystem.metaClassRegistry.getMetaClass(instance.getClass()) + metaClass.setProperty( instance, GrailsDomainClassProperty.ERRORS, errors) + } + + return valid } - @Override - boolean validate(D instance, Map arguments) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [arguments] as Object[]) - } - return super.validate(instance, arguments) + private void fireEvent(Object target, List<?> validatedFieldsList) { + ValidationEvent event = new ValidationEvent(datastore, target); + event.setValidatedFields(validatedFieldsList); + datastore.getApplicationContext().publishEvent(event); } - @Override - boolean validate(D instance, List fields) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [fields] as Object[]) + @SuppressWarnings("rawtypes") + private Errors filterErrors(Errors errors, Set validatedFields, Object target) { + if (validatedFields == null) return errors; + + ValidationErrors result = new ValidationErrors(target); + + final List allErrors = errors.getAllErrors(); + for (Object allError : allErrors) { + ObjectError error = (ObjectError) allError; + + if (error instanceof FieldError) { + FieldError fieldError = (FieldError) error; + if (!validatedFields.contains(fieldError.getField())) continue; + } + + result.addError(error); } - return super.validate(instance, fields) + + return result; + } + + /** + * Initializes the Errors property on target. The target will be assigned a new + * Errors property. If the target contains any binding errors, those binding + * errors will be copied in to the new Errors property. + * + * @param target object to initialize + * @return the new Errors object + */ + protected Errors setupErrorsProperty(Object target) { + HibernateRuntimeUtils.setupErrorsProperty target } }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClassProperty.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClassProperty.java index dc3b348..1eb1aee 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClassProperty.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClassProperty.java
@@ -14,13 +14,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import grails.util.GrailsNameUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; import org.springframework.beans.BeanUtils; import org.springframework.util.ReflectionUtils;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/IHibernateTemplate.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/IHibernateTemplate.java index 395519f..9096366 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/IHibernateTemplate.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/IHibernateTemplate.java
@@ -18,11 +18,17 @@ import java.io.Serializable; import java.util.Collection; +import groovy.lang.Closure; +import org.hibernate.Criteria; import org.hibernate.LockMode; +import org.hibernate.Query; import org.hibernate.SessionFactory; /** + * Template interface that can be used with both Hibernate 3 and Hibernate 4 + * * @author Burt Beckwith + * @author Graeme Rocher */ public interface IHibernateTemplate { @@ -46,6 +52,10 @@ void deleteAll(Collection<?> list); + void applySettings(Query query); + + void applySettings(Criteria criteria); + <T> T get(Class<T> type, Serializable key); <T> T get(Class<T> type, Serializable key, LockMode mode); @@ -55,4 +65,6 @@ void delete(Object o); SessionFactory getSessionFactory(); + + <T> T execute(Closure<T> callable); }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/AbstractGrailsDomainBinder.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/AbstractGrailsDomainBinder.java index a0910c6..3f6d484 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/AbstractGrailsDomainBinder.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/AbstractGrailsDomainBinder.java
@@ -14,16 +14,21 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.config.Config; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.plugins.GrailsPlugin; +import grails.plugins.GrailsPluginManager; +import grails.util.GrailsClassUtils; import grails.util.GrailsNameUtils; +import grails.validation.ConstrainedProperty; import groovy.lang.Closure; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; -import org.codehaus.groovy.grails.exceptions.GrailsDomainException; -import org.codehaus.groovy.grails.plugins.GrailsPlugin; -import org.codehaus.groovy.grails.plugins.GrailsPluginManager; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; import org.codehaus.groovy.runtime.DefaultGroovyMethods; +import org.grails.core.DefaultGrailsDomainClassProperty; +import org.grails.core.exceptions.GrailsDomainException; import org.hibernate.FetchMode; import org.hibernate.MappingException; import org.hibernate.cfg.*; @@ -1172,7 +1177,7 @@ } if (tableName == null) { String shortName = domainClass.getShortName(); - final GrailsApplication grailsApplication = domainClass.getGrailsApplication(); + final GrailsApplication grailsApplication = domainClass.getApplication(); if (grailsApplication != null) { final ApplicationContext mainContext = grailsApplication.getMainContext(); if (mainContext != null && mainContext.containsBean("pluginManager")) { @@ -1183,11 +1188,11 @@ boolean shouldApplyPluginPrefix = false; if (!shortName.toLowerCase().startsWith(pluginName.toLowerCase())) { final String pluginSpecificConfigProperty = "grails.gorm." + GrailsNameUtils.getPropertyName(pluginName) + ".table.prefix.enabled"; - final Map<String, Object> flatConfig = grailsApplication.getFlatConfig(); - if (flatConfig.containsKey(pluginSpecificConfigProperty)) { - shouldApplyPluginPrefix = Boolean.TRUE.equals(flatConfig.get(pluginSpecificConfigProperty)); + final Config config = grailsApplication.getConfig(); + if (config.containsKey(pluginSpecificConfigProperty)) { + shouldApplyPluginPrefix = config.getProperty(pluginSpecificConfigProperty, Boolean.class, false); } else { - shouldApplyPluginPrefix = Boolean.TRUE.equals(flatConfig.get("grails.gorm.table.prefix.enabled")); + shouldApplyPluginPrefix = config.getProperty("grails.gorm.table.prefix.enabled", Boolean.class, false); } } if (shouldApplyPluginPrefix) { @@ -1244,7 +1249,7 @@ Object o = GrailsClassUtils.getStaticPropertyValue(domainClass.getClazz(), GrailsDomainClassProperty.MAPPING); if (o != null || defaultMapping != null) { HibernateMappingBuilder builder = new HibernateMappingBuilder(domainClass.getFullName()); - GrailsApplication application = domainClass.getGrailsApplication(); + GrailsApplication application = domainClass.getApplication(); ApplicationContext ctx = null; if (application != null) { ctx = application.getMainContext(); @@ -1328,7 +1333,7 @@ * @param theClass The domain class in question * @return A Mapping object or null */ - public Mapping getMapping(Class<?> theClass) { + public static Mapping getMapping(Class<?> theClass) { return theClass == null ? null : MAPPING_CACHE.get(theClass); } @@ -1338,7 +1343,7 @@ * @param domainClass The domain class in question * @return A Mapping object or null */ - public Mapping getMapping(GrailsDomainClass domainClass) { + public static Mapping getMapping(GrailsDomainClass domainClass) { return domainClass == null ? null : MAPPING_CACHE.get(domainClass.getClazz()); }
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainConfiguration.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainConfiguration.java index c8d8ecd..f52a226 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainConfiguration.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainConfiguration.java
@@ -14,8 +14,9 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; + +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; /** * @author Graeme Rocher
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateNamedQueriesBuilder.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateNamedQueriesBuilder.groovy index a6ae77d..f6966f9 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateNamedQueriesBuilder.groovy +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateNamedQueriesBuilder.groovy
@@ -15,13 +15,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg +import grails.core.GrailsDomainClass import grails.util.GrailsNameUtils import groovy.lang.Closure; import java.lang.reflect.Modifier import java.util.List; -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.gorm.query.NamedQueriesBuilder import org.grails.datastore.mapping.model.PersistentEntity;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtilities.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtilities.java index 2f0933e..c20d45f 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtilities.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtilities.java
@@ -2,8 +2,8 @@ import java.util.List; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import org.codehaus.groovy.grails.orm.hibernate.AbstractGrailsHibernateDomainClass; public class HibernateUtilities {
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateException.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateException.java index 545d273..62cfdd2 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateException.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateException.java
@@ -15,7 +15,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate.exceptions; -import org.codehaus.groovy.grails.exceptions.GrailsException; + +import org.grails.core.exceptions.GrailsException; /** * Base exception class for errors related to Hibernate configuration in Grails.
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsQueryException.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsQueryException.java index e66724f..d8ba3f7 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsQueryException.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsQueryException.java
@@ -15,7 +15,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate.exceptions; -import org.codehaus.groovy.grails.exceptions.GrailsException; + +import org.grails.core.exceptions.GrailsException; /** * Base exception class for errors related to Domain class queries in Grails.
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java new file mode 100644 index 0000000..bd6f2dc --- /dev/null +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java
@@ -0,0 +1,125 @@ +/* + * Copyright 2004-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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.codehaus.groovy.grails.orm.hibernate.proxy; + + +import grails.core.support.proxy.EntityProxyHandler; +import groovy.lang.GroovyObject; +import groovy.lang.GroovySystem; +import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; +import org.hibernate.Hibernate; +import org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.HibernateProxyHelper; +import org.hibernate.proxy.LazyInitializer; + +/** + * Implementation of the ProxyHandler interface for Hibernate. + * + * @author Graeme Rocher + * @since 1.2.2 + */ +public class SimpleHibernateProxyHandler implements EntityProxyHandler { + + public boolean isInitialized(Object o) { + if (o instanceof HibernateProxy) { + return !((HibernateProxy)o).getHibernateLazyInitializer().isUninitialized(); + } + return true; + } + + public boolean isInitialized(Object obj, String associationName) { + try { + Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); + return Hibernate.isInitialized(proxy); + } + catch (RuntimeException e) { + return false; + } + } + + public Object unwrapIfProxy(Object instance) { + if (instance instanceof HibernateProxy) { + final HibernateProxy proxy = (HibernateProxy)instance; + return unwrapProxy(proxy); + } + return instance; + } + + public Object unwrapProxy(final HibernateProxy proxy) { + final LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer(); + if (lazyInitializer.isUninitialized()) { + lazyInitializer.initialize(); + } + final Object obj = lazyInitializer.getImplementation(); + if (obj != null) { + ensureCorrectGroovyMetaClass(obj, obj.getClass()); + } + return obj; + } + + /** + * Ensures the meta class is correct for a given class + * + * @param target The GroovyObject + * @param persistentClass The persistent class + */ + private static void ensureCorrectGroovyMetaClass(Object target, Class<?> persistentClass) { + if (target instanceof GroovyObject) { + GroovyObject go = ((GroovyObject)target); + if (!go.getMetaClass().getTheClass().equals(persistentClass)) { + go.setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(persistentClass)); + } + } + } + + + public HibernateProxy getAssociationProxy(Object obj, String associationName) { + try { + Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); + if (proxy instanceof HibernateProxy) { + return (HibernateProxy) proxy; + } + return null; + } + catch (RuntimeException e) { + return null; + } + } + + public boolean isProxy(Object o) { + return (o instanceof HibernateProxy); + } + + public void initialize(Object o) { + if (o instanceof HibernateProxy) { + final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer(); + if (hibernateLazyInitializer.isUninitialized()) { + hibernateLazyInitializer.initialize(); + } + } + } + + public Object getProxyIdentifier(Object o) { + if (o instanceof HibernateProxy) { + return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); + } + return null; + } + + public Class<?> getProxiedClass(Object o) { + return HibernateProxyHelper.getClassWithoutInitializingProxy(o); + } +}
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 906e42f..ba69ae8 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java
@@ -1,10 +1,9 @@ package org.codehaus.groovy.grails.orm.hibernate.query; +import grails.core.GrailsApplication; import grails.util.CollectionUtils; +import grails.util.GrailsClassUtils; import groovy.lang.*; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; import org.grails.datastore.mapping.query.api.*; import org.hibernate.*; import org.hibernate.Criteria;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateQuery.java index 2d5cf89..c930706 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateQuery.java
@@ -21,22 +21,27 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.persistence.FetchType; +import grails.core.support.proxy.ProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateSession; import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; +import org.codehaus.groovy.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; +import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping; +import org.codehaus.groovy.grails.orm.hibernate.proxy.SimpleHibernateProxyHandler; +import org.grails.datastore.gorm.finders.DynamicFinder; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Embedded; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.hibernate.Criteria; -import org.hibernate.FetchMode; -import org.hibernate.SessionFactory; +import org.hibernate.*; import org.hibernate.criterion.*; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.function.SQLFunction; @@ -63,6 +68,7 @@ protected static final String ALIAS = "_alias"; protected static ConversionService conversionService = new DefaultConversionService(); protected static Field opField = ReflectionUtils.findField(SimpleExpression.class, "op"); + private static final Map<String, Boolean> JOIN_STATUS_CACHE = new ConcurrentHashMap<String, Boolean>(); static { ReflectionUtils.makeAccessible(opField); } @@ -77,10 +83,15 @@ protected LinkedList<PersistentEntity> entityStack = new LinkedList<PersistentEntity>(); protected LinkedList<Association> associationStack = new LinkedList<Association>(); protected LinkedList aliasInstanceStack = new LinkedList(); + private boolean hasJoins = false; + protected ProxyHandler proxyHandler = new SimpleHibernateProxyHandler(); protected AbstractHibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); this.criteria = criteria; + if(entity != null) { + initializeJoinStatus(); + } } protected AbstractHibernateQuery(DetachedCriteria criteria) { @@ -88,6 +99,16 @@ this.detachedCriteria = criteria; } + private void initializeJoinStatus() { + Boolean cachedStatus = JOIN_STATUS_CACHE.get(entity.getName()); + if(cachedStatus != null) hasJoins = cachedStatus; + else { + for(Association a : entity.getAssociations()) { + if( a.getFetchStrategy() == FetchType.EAGER ) hasJoins = true; + } + } + } + protected AbstractHibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { this(subCriteria, session, associatedEntity); alias = newAlias; @@ -494,24 +515,88 @@ } @Override + public Query cache(boolean cache) { + criteria.setCacheable(true); + + return super.cache(cache); + } + + @Override + public Query lock(boolean lock) { + criteria.setCacheable(false); + criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); + return super.lock(lock); + } + + @Override public Query order(Order order) { super.order(order); - if(criteria != null) { - criteria.addOrder(order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(calculatePropertyName(order.getProperty())) : - org.hibernate.criterion.Order.desc(calculatePropertyName(order.getProperty()))); - }else if(detachedCriteria != null) { - detachedCriteria.addOrder(order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(calculatePropertyName(order.getProperty())) : - org.hibernate.criterion.Order.desc(calculatePropertyName(order.getProperty()))); + String property = order.getProperty(); + + int i = property.indexOf('.'); + if(i > -1) { + String sortHead = property.substring(0,i); + String sortTail = property.substring(i + 1); + + PersistentProperty persistentProperty = entity.getPropertyByName(sortHead); + + if(persistentProperty instanceof Association) { + Association a = (Association) persistentProperty; + if(persistentProperty instanceof Embedded) { + addSimpleOrder(order, property); + } + else { + if(criteria != null) { + Criteria subCriteria = criteria.createCriteria(sortHead); + addOrderToCriteria(subCriteria, sortTail, order); + } + else if(detachedCriteria != null) { + DetachedCriteria subDetachedCriteria = detachedCriteria.createCriteria(sortHead); + addOrderToDetachedCriteria(subDetachedCriteria, sortTail, order); + } + } + } } + else { + addSimpleOrder(order, property); + } + return this; } + private void addSimpleOrder(Order order, String property) { + Criteria c = criteria; + if(c != null) { + addOrderToCriteria(c, property, order); + }else { + DetachedCriteria dc = detachedCriteria; + addOrderToDetachedCriteria(dc, property, order); + } + } + + private void addOrderToDetachedCriteria(DetachedCriteria dc, String property, Order order) { + if(dc != null) { + org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? + org.hibernate.criterion.Order.asc(calculatePropertyName(property)) : + org.hibernate.criterion.Order.desc(calculatePropertyName(property)); + dc.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); + + } + } + + private void addOrderToCriteria(Criteria c, String property, Order order) { + org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? + org.hibernate.criterion.Order.asc(calculatePropertyName(property)) : + org.hibernate.criterion.Order.desc(calculatePropertyName(property)); + + c.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); + } + @Override public Query join(String property) { + this.hasJoins = true; if(criteria != null) criteria.setFetchMode(property, FetchMode.JOIN); else if(detachedCriteria != null) @@ -521,6 +606,7 @@ @Override public Query select(String property) { + this.hasJoins = true; if(criteria != null) criteria.setFetchMode(property, FetchMode.SELECT); else if(detachedCriteria != null) @@ -536,17 +622,37 @@ if (hibernateProjectionList != null) { org.hibernate.criterion.ProjectionList projectionList = hibernateProjectionList.getHibernateProjectionList(); projectionLength = projectionList.getLength(); - criteria.setProjection(projectionList); + if(projectionLength > 0) { + criteria.setProjection(projectionList); + } } if (projectionLength < 2) { criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); } + applyDefaultSortOrderAndCaching(); applyFetchStrategies(); + + return criteria.list(); } + protected void applyDefaultSortOrderAndCaching() { + if(this.orderBy.isEmpty() && entity != null) { + Mapping mapping = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); + if(mapping != null) { + if(queryCache == null && mapping.getCache() != null && mapping.getCache().isEnabled()) { + criteria.setCacheable(true); + } + + Map sortMap = mapping.getSort().getNamesAndDirections(); + DynamicFinder.applySortForMap(this, sortMap, true); + + } + } + } + protected void applyFetchStrategies() { for (Map.Entry<String, FetchType> entry : fetchStrategies.entrySet()) { switch(entry.getValue()) { @@ -579,10 +685,31 @@ criteria.setProjection(hibernateProjectionList.getHibernateProjectionList()); } criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); + applyDefaultSortOrderAndCaching(); applyFetchStrategies(); - return criteria.uniqueResult(); + + if(hasJoins) { + try { + return proxyHandler.unwrapIfProxy(criteria.uniqueResult()); + } catch (NonUniqueResultException e) { + return singleResultViaListCall(); + } + } + else { + return singleResultViaListCall(); + } } + private Object singleResultViaListCall() { + criteria.setMaxResults(1); + List results = criteria.list(); + if(results.size()>0) { + return proxyHandler.unwrapIfProxy(results.get(0)); + } + return null; + } + + @Override protected List executeQuery(PersistentEntity entity, Junction criteria) { return list(); @@ -779,6 +906,19 @@ } @Override + public Query order(Order order) { + + Order.Direction direction = order.getDirection(); + switch(direction) { + case ASC: + assocationCriteria.addOrder(org.hibernate.criterion.Order.asc(order.getProperty())); + case DESC: + assocationCriteria.addOrder(org.hibernate.criterion.Order.desc(order.getProperty())); + } + return super.order(order); + } + + @Override public Query isEmpty(String property) { org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); addToCriteria(criterion);
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java new file mode 100644 index 0000000..78287b9 --- /dev/null +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
@@ -0,0 +1,217 @@ +package org.codehaus.groovy.grails.orm.hibernate.query; + +import grails.util.GrailsClassUtils; +import org.codehaus.groovy.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; +import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping; +import org.grails.datastore.gorm.finders.DynamicFinder; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Embedded; +import org.hibernate.Criteria; +import org.hibernate.FetchMode; +import org.hibernate.FlushMode; +import org.hibernate.LockMode; +import org.hibernate.criterion.Order; +import org.springframework.core.convert.ConversionService; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.Map; + + +/** + * Utility methods for configuring Hibernate queries + * + * @author Graeme Rocher + * @since 4.0 + */ +public class GrailsHibernateQueryUtils { + + /** + * Populates criteria arguments for the given target class and arguments map + * + * @param entity The {@link org.grails.datastore.mapping.model.PersistentEntity} instance + * @param c The criteria instance + * @param argMap The arguments map + */ + @SuppressWarnings("rawtypes") + public static void populateArgumentsForCriteria(PersistentEntity entity, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { + Integer maxParam = null; + Integer offsetParam = null; + if (argMap.containsKey(DynamicFinder.ARGUMENT_MAX)) { + maxParam = conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_MAX),Integer.class); + } + if (argMap.containsKey(DynamicFinder.ARGUMENT_OFFSET)) { + offsetParam = conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_OFFSET),Integer.class); + } + if (argMap.containsKey(DynamicFinder.ARGUMENT_FETCH_SIZE)) { + c.setFetchSize(conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_FETCH_SIZE),Integer.class)); + } + if (argMap.containsKey(DynamicFinder.ARGUMENT_TIMEOUT)) { + c.setTimeout(conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_TIMEOUT),Integer.class)); + } + if (argMap.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { + c.setFlushMode(convertFlushMode(argMap.get(DynamicFinder.ARGUMENT_FLUSH_MODE))); + } + if (argMap.containsKey(DynamicFinder.ARGUMENT_READ_ONLY)) { + c.setReadOnly(GrailsClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_READ_ONLY, argMap)); + } + String orderParam = (String)argMap.get(DynamicFinder.ARGUMENT_ORDER); + Object fetchObj = argMap.get(DynamicFinder.ARGUMENT_FETCH); + if (fetchObj instanceof Map) { + Map fetch = (Map)fetchObj; + for (Object o : fetch.keySet()) { + String associationName = (String) o; + c.setFetchMode(associationName, getFetchMode(fetch.get(associationName))); + } + } + + final int max = maxParam == null ? -1 : maxParam; + final int offset = offsetParam == null ? -1 : offsetParam; + if (max > -1) { + c.setMaxResults(max); + } + if (offset > -1) { + c.setFirstResult(offset); + } + if (GrailsClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_LOCK, argMap)) { + c.setLockMode(LockMode.PESSIMISTIC_WRITE); + c.setCacheable(false); + } + else { + if (argMap.containsKey(DynamicFinder.ARGUMENT_CACHE)) { + c.setCacheable(GrailsClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_CACHE, argMap)); + } else { + cacheCriteriaByMapping(entity.getJavaClass(), c); + } + } + + final Object sortObj = argMap.get(DynamicFinder.ARGUMENT_SORT); + if (sortObj != null) { + boolean ignoreCase = true; + Object caseArg = argMap.get(DynamicFinder.ARGUMENT_IGNORE_CASE); + if (caseArg instanceof Boolean) { + ignoreCase = (Boolean) caseArg; + } + if (sortObj instanceof Map) { + Map sortMap = (Map) sortObj; + for (Object sort : sortMap.keySet()) { + final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; + addOrderPossiblyNested(c, entity, (String) sort, order, ignoreCase); + } + } else { + final String sort = (String) sortObj; + final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase(orderParam) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; + addOrderPossiblyNested( c, entity, sort, order, ignoreCase); + } + } + else if (useDefaultMapping) { + Mapping m = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); + if (m != null) { + Map sortMap = m.getSort().getNamesAndDirections(); + for (Object sort : sortMap.keySet()) { + final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; + addOrderPossiblyNested(c, entity, (String) sort, order, true); + } + } + } + } + + /** + * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). + */ + private static void addOrderPossiblyNested(Criteria c, PersistentEntity entity, String sort, String order, boolean ignoreCase) { + int firstDotPos = sort.indexOf("."); + if (firstDotPos == -1) { + addOrder(c, sort, order, ignoreCase); + } else { // nested property + String sortHead = sort.substring(0,firstDotPos); + String sortTail = sort.substring(firstDotPos+1); + PersistentProperty property = entity.getPropertyByName(sortHead); + if (property instanceof Embedded) { + // embedded objects cannot reference entities (at time of writing), so no more recursion needed + addOrder(c, sort, order, ignoreCase); + } else if(property instanceof Association) { + Association a = (Association) property; + Criteria subCriteria = c.createCriteria(sortHead); + PersistentEntity associatedEntity = a.getAssociatedEntity(); + Class<?> propertyTargetClass = associatedEntity.getJavaClass(); + cacheCriteriaByMapping(propertyTargetClass, subCriteria); + addOrderPossiblyNested( subCriteria, associatedEntity, sortTail, order, ignoreCase); // Recurse on nested sort + } + } + } + + /** + * Configures the criteria instance to cache based on the configured mapping. + * + * @param targetClass The target class + * @param criteria The criteria + */ + private static void cacheCriteriaByMapping(Class<?> targetClass, Criteria criteria) { + Mapping m = AbstractGrailsDomainBinder.getMapping(targetClass); + if (m != null && m.getCache() != null && m.getCache().getEnabled()) { + criteria.setCacheable(true); + } + } + + private static FlushMode convertFlushMode(Object object) { + if (object == null) { + return null; + } + if (object instanceof FlushMode) { + return (FlushMode)object; + } + return FlushModeConverter.valueOf(object.toString()); + } + /** + * Add order directly to criteria. + */ + private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { + if (DynamicFinder.ORDER_DESC.equals(order)) { + c.addOrder(ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); + } + else { + c.addOrder(ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort)); + } + } + + /** + * Retrieves the fetch mode for the specified instance; otherwise returns the default FetchMode. + * + * @param object The object, converted to a string + * @return The FetchMode + */ + public static FetchMode getFetchMode(Object object) { + String name = object != null ? object.toString() : "default"; + if (name.equalsIgnoreCase(FetchMode.JOIN.toString()) || name.equalsIgnoreCase("eager")) { + return FetchMode.JOIN; + } + if (name.equalsIgnoreCase(FetchMode.SELECT.toString()) || name.equalsIgnoreCase("lazy")) { + return FetchMode.SELECT; + } + return FetchMode.DEFAULT; + } + + static class FlushModeConverter { + static Method conversionMethod; + static { + try { + conversionMethod = ReflectionUtils.findMethod(FlushMode.class, "parse", String.class); + } catch(Throwable t) { + conversionMethod = ReflectionUtils.findMethod(FlushMode.class, "valueOf", String.class); + } + + ReflectionUtils.makeAccessible(conversionMethod); + } + + static FlushMode valueOf(String str) { + try { + return (FlushMode)conversionMethod.invoke(FlushMode.class, str); + } catch (Throwable t) { + return FlushMode.COMMIT; + } + } + } +}
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractAggregatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractAggregatePersistenceContextInterceptor.java index 1d5f063..b1a550a 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractAggregatePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractAggregatePersistenceContextInterceptor.java
@@ -18,7 +18,7 @@ import java.util.ArrayList; import java.util.List; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; +import grails.persistence.support.PersistenceContextInterceptor; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java index 522d74e..4488f9b 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java
@@ -15,29 +15,38 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; +import grails.config.Config; +import grails.core.GrailsDomainClassProperty; +import grails.core.support.GrailsConfigurationAware; +import grails.persistence.support.PersistenceContextInterceptor; import grails.util.Holders; import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; import org.hibernate.SessionFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** - * Abstract implementation of the {@link org.codehaus.groovy.grails.support.PersistenceContextInterceptor} interface that supports multiple data sources + * Abstract implementation of the {@link grails.persistence.support.PersistenceContextInterceptor} interface that supports multiple data sources * * @author Graeme Rocher * @since 2.0.7 */ -public abstract class AbstractMultipleDataSourceAggregatePersistenceContextInterceptor implements PersistenceContextInterceptor, InitializingBean, ApplicationContextAware { +public abstract class AbstractMultipleDataSourceAggregatePersistenceContextInterceptor implements PersistenceContextInterceptor, InitializingBean, ApplicationContextAware, GrailsConfigurationAware { protected List<PersistenceContextInterceptor> interceptors = new ArrayList<PersistenceContextInterceptor>(); protected ApplicationContext applicationContext; + protected Config config; + + + @Override + public void setConfiguration(Config co) { + this.config = co; + } public boolean isOpen() { for (PersistenceContextInterceptor interceptor : interceptors) { @@ -132,13 +141,15 @@ private List<String> aggregateDataSourceNames() { List<String> dataSourceNames = new ArrayList<String>(); - Set<String> configKeys = Holders.getConfig().keySet(); - if (configKeys.contains("dataSource") && applicationContext.containsBean("dataSource")) { - dataSourceNames.add(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE); - } - for (String name : configKeys) { - if (name.startsWith("dataSource_") && applicationContext.containsBean(name)) { - dataSourceNames.add(name.replaceFirst("dataSource_", "")); + if(config != null && applicationContext != null) { + Set<String> configKeys = config.keySet(); + if (configKeys.contains("dataSource") && applicationContext.containsBean("dataSource")) { + dataSourceNames.add(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE); + } + for (String name : configKeys) { + if (name.startsWith("dataSource_") && applicationContext.containsBean(name)) { + dataSourceNames.add(name.replaceFirst("dataSource_", "")); + } } } return dataSourceNames;
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy new file mode 100644 index 0000000..264efc4 --- /dev/null +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
@@ -0,0 +1,130 @@ +package org.codehaus.groovy.grails.orm.hibernate.support + +import grails.core.GrailsDomainClassProperty +import grails.core.support.proxy.ProxyHandler +import grails.validation.ValidationErrors +import groovy.transform.CompileStatic +import org.codehaus.groovy.grails.orm.hibernate.proxy.SimpleHibernateProxyHandler +import org.codehaus.groovy.runtime.StringGroovyMethods +import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.datastore.mapping.model.types.Association +import org.grails.datastore.mapping.model.types.OneToOne +import org.springframework.beans.BeanWrapper +import org.springframework.beans.BeanWrapperImpl +import org.springframework.core.convert.ConversionService +import org.springframework.validation.Errors +import org.springframework.validation.FieldError + +/** + * Utility methods used at runtime by the GORM for Hibernate implementation + * + * @author Graeme Rocher + * @since 4.0 + */ +@CompileStatic +class HibernateRuntimeUtils { + private static ProxyHandler proxyHandler = new SimpleHibernateProxyHandler(); + + /** + * Initializes the Errors property on target. The target will be assigned a new + * Errors property. If the target contains any binding errors, those binding + * errors will be copied in to the new Errors property. + * + * @param target object to initialize + * @return the new Errors object + */ + public static Errors setupErrorsProperty(Object target) { + MetaClass mc = GroovySystem.metaClassRegistry.getMetaClass(target.getClass()) + + def errors = new ValidationErrors(target) + + Errors originalErrors = (Errors) mc.getProperty(target, GrailsDomainClassProperty.ERRORS) + for (Object o in originalErrors.fieldErrors) { + FieldError fe = (FieldError)o + if (fe.isBindingFailure()) { + errors.addError(new FieldError(fe.getObjectName(), + fe.field, + fe.rejectedValue, + fe.bindingFailure, + fe.codes, + fe.arguments, + fe.defaultMessage)) + } + } + + mc.setProperty(target, GrailsDomainClassProperty.ERRORS, errors); + return errors; + } + + public static void autoAssociateBidirectionalOneToOnes(PersistentEntity entity, Object target) { + for (Association association : entity.associations) { + if (!(association instanceof OneToOne) || !association.bidirectional || !association.owningSide) { + continue + } + + def propertyName = association.name + if (!proxyHandler.isInitialized(target, propertyName)) { + continue + } + + def otherSide = association.inverseSide + + if (otherSide == null) { + continue + } + + BeanWrapper bean = new BeanWrapperImpl(target) + Object inverseObject = bean.getPropertyValue(propertyName) + if (inverseObject == null) { + continue + } + + def otherSidePropertyName = otherSide.getName() + if (!proxyHandler.isInitialized(inverseObject, otherSidePropertyName)) { + continue + } + + def inverseBean = new BeanWrapperImpl(inverseObject) + def propertyValue = inverseBean.getPropertyValue(otherSidePropertyName) + if (propertyValue == null) { + inverseBean.setPropertyValue(otherSidePropertyName, target) + } + } + } + + static Object convertValueToType(Object passedValue, Class targetType, ConversionService conversionService) { + // workaround for GROOVY-6127, do not assign directly in parameters before it's fixed + Object value = passedValue + if(targetType != null && value != null && !(value in targetType)) { + if (value instanceof CharSequence) { + value = value.toString() + if(value in targetType) { + return value + } + } + try { + if (value instanceof Number && (targetType==Long || targetType==Integer)) { + if(targetType == Long) { + value = ((Number)value).toLong() + } else { + value = ((Number)value).toInteger() + } + } else if (value instanceof String && targetType in Number) { + String strValue = value.trim() + if(targetType == Long) { + value = Long.parseLong(strValue) + } else if (targetType == Integer) { + value = Integer.parseInt(strValue) + } else { + value = StringGroovyMethods.asType(strValue, targetType) + } + } else { + value = conversionService.convert(value, targetType) + } + } catch (e) { + // ignore + } + } + return value + } +}
diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SessionFactoryAwarePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SessionFactoryAwarePersistenceContextInterceptor.java index 5f2c579..8cd1dbc 100644 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SessionFactoryAwarePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SessionFactoryAwarePersistenceContextInterceptor.java
@@ -15,16 +15,16 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; +import grails.persistence.support.PersistenceContextInterceptor; import org.hibernate.SessionFactory; /** - * Interface for {@link org.codehaus.groovy.grails.support.PersistenceContextInterceptor} instances that are aware of the {@link org.hibernate.SessionFactory} + * Interface for {@link grails.persistence.support.PersistenceContextInterceptor} instances that are aware of the {@link org.hibernate.SessionFactory} * * @author Graeme Rocher * @since 2.0.7 */ -public interface SessionFactoryAwarePersistenceContextInterceptor extends PersistenceContextInterceptor{ +public interface SessionFactoryAwarePersistenceContextInterceptor extends PersistenceContextInterceptor { void setSessionFactory(SessionFactory sessionFactory); }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java similarity index 73% rename from grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java rename to grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java index bc124ae..d7a645d 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java
@@ -1,5 +1,4 @@ -/* - * Copyright 2004-2005 Graeme Rocher +/* Copyright 2004-2005 Graeme Rocher * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +14,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate.validation; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import org.codehaus.groovy.grails.orm.hibernate.AbstractGrailsHibernateDomainClass; +import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; import org.codehaus.groovy.grails.validation.AbstractConstraint; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.core.lifecycle.ShutdownOperations; import org.hibernate.SessionFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -50,14 +49,7 @@ this.applicationContext = applicationContext; } - public GrailsHibernateTemplate getHibernateTemplate() { - SessionFactory sf = sessionFactory.get(); - if (sf == null) { - sf = applicationContext.getBean("sessionFactory", SessionFactory.class); - } - GrailsApplication app = applicationContext.getBean("grailsApplication", GrailsApplication.class); - return new GrailsHibernateTemplate(sf, app, GrailsHibernateTemplate.FLUSH_NEVER); - } + public abstract IHibernateTemplate getHibernateTemplate(); /** * Returns whether the constraint supports being applied against the specified type; @@ -74,7 +66,6 @@ * * @return true if it is */ - @Override public boolean isValid() { if (applicationContext.containsBean("sessionFactory")) { GrailsApplication grailsApplication = applicationContext.getBean( @@ -83,8 +74,8 @@ DomainClassArtefactHandler.TYPE, constraintOwningClass.getName()); if (domainClass != null) { String mappingStrategy = domainClass.getMappingStrategy(); - return mappingStrategy.equals(GrailsDomainClass.GORM) || - mappingStrategy.equals(GrailsHibernateDomainClass.HIBERNATE); + return mappingStrategy.equals(GrailsDomainClass.GORM) + || mappingStrategy.equals(AbstractGrailsHibernateDomainClass.HIBERNATE); } } return false;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java similarity index 90% rename from grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java rename to grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java index c3fe4ee..7335a91 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java
@@ -14,6 +14,7 @@ */ package org.codehaus.groovy.grails.orm.hibernate.validation; +import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; import org.codehaus.groovy.grails.validation.Constraint; import org.springframework.context.ApplicationContextAware; import org.springframework.orm.hibernate3.HibernateTemplate; @@ -31,5 +32,5 @@ * * @return the template */ - HibernateTemplate getHibernateTemplate(); + IHibernateTemplate getHibernateTemplate(); }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java similarity index 97% rename from grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java rename to grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java index 6535d91..4b13f44 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java +++ b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java
@@ -14,9 +14,9 @@ */ package org.codehaus.groovy.grails.orm.hibernate.validation; -import org.codehaus.groovy.grails.exceptions.GrailsDomainException; import org.codehaus.groovy.grails.validation.Constraint; import org.codehaus.groovy.grails.validation.ConstraintFactory; +import org.grails.core.exceptions.GrailsDomainException; import org.springframework.context.ApplicationContext; import org.springframework.util.Assert;
diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index c450389..d7e1bc0 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle
@@ -9,6 +9,12 @@ optional("org.grails:grails-web:$grailsVersion") { transitive = false } + optional("org.grails:grails-web-common:$grailsVersion") { + transitive = false + } + optional("org.grails:grails-web-url-mappings:$grailsVersion") { + transitive = false + } optional("org.grails:grails-spring:$grailsVersion") { transitive = false } @@ -60,4 +66,4 @@ compileTestGroovy { groovyOptions.fork(memoryMaximumSize: '1024m') -} \ No newline at end of file +}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy index e7f3391..27ce185 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy
@@ -72,11 +72,11 @@ super(persistentClasses.toList()) } - HibernateDatastoreSpringInitializer(Properties hibernateProperties, Collection<Class> persistentClasses) { + HibernateDatastoreSpringInitializer(Map hibernateProperties, Collection<Class> persistentClasses) { super(hibernateProperties, persistentClasses) } - HibernateDatastoreSpringInitializer(Properties hibernateProperties, Class... persistentClasses) { + HibernateDatastoreSpringInitializer(Map hibernateProperties, Class... persistentClasses) { super(hibernateProperties, persistentClasses.toList()) }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/plugin/hibernate3/HibernatePluginSupport.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/grails/plugin/hibernate3/HibernatePluginSupport.groovy index 265f2c6..6fb3b76 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/plugin/hibernate3/HibernatePluginSupport.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/plugin/hibernate3/HibernatePluginSupport.groovy
@@ -15,15 +15,14 @@ */ package grails.plugin.hibernate3 +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.validation.ConstrainedProperty +import grails.validation.ConstraintsEvaluator import groovy.transform.CompileStatic import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration -import org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator -import org.codehaus.groovy.grails.commons.spring.RuntimeSpringConfiguration import org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore @@ -45,9 +44,10 @@ import org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.codehaus.groovy.grails.validation.ConstraintsEvaluator import org.grails.datastore.mapping.model.MappingContext +import org.grails.spring.DefaultRuntimeSpringConfiguration +import org.grails.spring.RuntimeSpringConfiguration +import org.grails.web.servlet.context.support.GrailsRuntimeConfigurator import org.hibernate.EmptyInterceptor import org.hibernate.cfg.ImprovedNamingStrategy import org.springframework.beans.factory.config.BeanDefinition @@ -181,7 +181,7 @@ catch (Throwable t) { hibConfig.cache.region.factory_class='net.sf.ehcache.hibernate.EhCacheRegionFactory' log.error """WARNING: Your cache provider is set to '${cacheProvider}' in DataSource.groovy, however the class for this provider cannot be found. -Using Grails' default cache region factory: 'net.sf.ehcache.hibernate.EhCacheRegionFactory'""" +Using Grails' default cache region factory: 'net.sf.ehcache.hibernate.EhCacheRegionFactory'""",t } } else if (!(hibConfig.cache.useCacheProvider) && (cacheProvider=='org.hibernate.cache.EhCacheProvider' || cacheProvider=='net.sf.ehcache.hibernate.EhCacheProvider')) { hibConfig.cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' @@ -199,7 +199,7 @@ } catch (Throwable t) { log.error """WARNING: You've configured a custom Hibernate naming strategy '$namingStrategy' in DataSource.groovy, however the class cannot be found. -Using Grails' default naming strategy: '${ImprovedNamingStrategy.name}'""" +Using Grails' default naming strategy: '${ImprovedNamingStrategy.name}'""",t grailsDomainBinder.configureNamingStrategy datasourceName, ImprovedNamingStrategy }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java index e2dda10..f80ee75 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java
@@ -14,6 +14,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClassProperty; import groovy.lang.GroovySystem; import groovy.lang.MetaClassRegistry; @@ -27,8 +29,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration; import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java index f8f9ac9..b591e99 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java
@@ -15,6 +15,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.config.Config; +import grails.core.GrailsDomainClass; import groovy.lang.GroovySystem; import groovy.util.ConfigObject; @@ -22,14 +24,13 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.codehaus.groovy.grails.commons.AnnotationDomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventListener; import org.codehaus.groovy.grails.orm.hibernate.support.SoftKey; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.grails.core.artefact.AnnotationDomainClassArtefactHandler; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.gorm.timestamp.DefaultTimestampProvider; import org.grails.datastore.gorm.timestamp.TimestampProvider; import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; @@ -63,10 +64,10 @@ private TimestampProvider timestampProvider = new DefaultTimestampProvider(); - public EventTriggeringInterceptor(HibernateDatastore datastore, ConfigObject co) { + public EventTriggeringInterceptor(HibernateDatastore datastore, Config co) { super(datastore); - Object failOnErrorConfig = co.flatten().get("grails.gorm.failOnError"); + Object failOnErrorConfig = co.getProperty("grails.gorm.failOnError", Object.class); if (failOnErrorConfig instanceof List) { failOnError = true; failOnErrorPackages = (List<?>)failOnErrorConfig; @@ -248,5 +249,5 @@ public void setTimestampProvider(TimestampProvider timestampProvider) { this.timestampProvider = timestampProvider; - } + } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java index b266238..e35a3fc 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java
@@ -17,7 +17,7 @@ import java.util.Collection; -import org.codehaus.groovy.grails.commons.GrailsApplication; +import grails.core.GrailsApplication; import org.hibernate.EntityMode; import org.hibernate.MappingException; import org.hibernate.SessionFactory;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java index 7cf9acc..cfca5bd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java
@@ -15,13 +15,16 @@ */ package org.codehaus.groovy.grails.orm.hibernate; -import org.codehaus.groovy.grails.commons.GrailsApplication; +import grails.core.GrailsApplication; +import groovy.lang.Closure; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.hibernate.Criteria; import org.hibernate.FlushMode; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -54,6 +57,12 @@ setFlushMode(defaultFlushMode); } + @Override + public <T> T execute(Closure<T> callable) { + HibernateCallback<T> hibernateCallback = DefaultGroovyMethods.asType(callable, HibernateCallback.class); + return execute(hibernateCallback); + } + private void initialize(GrailsApplication application) { setExposeNativeSession(true); if (application != null) {
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java index 53ea8bf..d14b796 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java
@@ -14,12 +14,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.config.Config; +import grails.core.GrailsApplication; +import grails.core.support.GrailsApplicationAware; import groovy.util.ConfigObject; import java.util.Map; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.MappingContext; import org.hibernate.SessionFactory; @@ -39,15 +40,15 @@ private int defaultFlushMode; - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config) { super(mappingContext, sessionFactory, config); } - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { + + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config, ApplicationContext applicationContext) { this(mappingContext, sessionFactory, config, applicationContext, GrailsHibernateTemplate.FLUSH_AUTO); } - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext, int defaultFlushMode) { + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config, ApplicationContext applicationContext, int defaultFlushMode) { super(mappingContext, sessionFactory, config, applicationContext); this.defaultFlushMode = defaultFlushMode; }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy index a2a15ef..1a6451c 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy
@@ -14,29 +14,11 @@ */ package org.codehaus.groovy.grails.orm.hibernate -import grails.util.GrailsNameUtils +import grails.core.GrailsApplication import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsClassUtils -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.orm.hibernate.metaclass.CountByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByBooleanPropertyPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByBooleanPropertyPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindOrCreateByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindOrSaveByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ListOrderByPersistentMethod import org.grails.datastore.gorm.GormInstanceApi import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.PersistentEntity -import org.springframework.beans.BeanUtils -import org.springframework.context.ApplicationContext import org.springframework.transaction.PlatformTransactionManager /** @@ -53,19 +35,6 @@ super(datastore, transactionManager, grailsApplication) } - protected List<FinderMethod> createDynamicFinders() { - HibernateDatastore hibernateDatastore = (HibernateDatastore)datastore - def sessionFactory = hibernateDatastore.sessionFactory - [new FindAllByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindAllByBooleanPropertyPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindOrCreateByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindOrSaveByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindByBooleanPropertyPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new CountByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new ListOrderByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader)] - } - protected <D> GormValidationApi<D> getValidationApi(Class<D> cls) { new HibernateGormValidationApi<D>(cls, (HibernateDatastore)datastore, classLoader) }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy index a6df315..20e21f6 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy
@@ -15,18 +15,17 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil -import org.codehaus.groovy.grails.orm.hibernate.metaclass.MergePersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod -import org.hibernate.LockMode +import org.grails.core.artefact.DomainClassArtefactHandler +import org.hibernate.FlushMode +import org.hibernate.Session import org.hibernate.engine.EntityEntry import org.hibernate.engine.SessionImplementor +import org.hibernate.engine.Status import org.hibernate.proxy.HibernateProxy -import org.springframework.dao.DataAccessException /** * The implementation of the GORM instance API contract for Hibernate. @@ -37,28 +36,23 @@ @CompileStatic class HibernateGormInstanceApi<D> extends AbstractHibernateGormInstanceApi<D> { - protected SavePersistentMethod saveMethod - protected MergePersistentMethod mergeMethod protected GrailsHibernateTemplate hibernateTemplate protected InstanceApiHelper instanceApiHelper HibernateGormInstanceApi(Class<D> persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) + super(persistentClass, datastore, classLoader, null) - def mappingContext = datastore.mappingContext def grailsApplication = datastore.getGrailsApplication() if (grailsApplication) { GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.name) config = (Map)grailsApplication.getFlatConfig().get('grails.gorm') - saveMethod = new SavePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) - mergeMethod = new MergePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication, datastore.getDefaultFlushMode()) - cacheQueriesByDefault = GrailsHibernateUtil.isCacheQueriesByDefault(grailsApplication) } else { hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) hibernateTemplate.setFlushMode(datastore.getDefaultFlushMode()) } + super.hibernateTemplate = hibernateTemplate instanceApiHelper = new InstanceApiHelper(hibernateTemplate) } @@ -142,107 +136,25 @@ } @Override - D lock(D instance) { - hibernateTemplate.lock(instance, LockMode.UPGRADE) - } + void setObjectToReadWrite(Object target) { + hibernateTemplate.execute { Session session -> + if (session.contains(target) && proxyHandler.isInitialized(target)) { + SessionImplementor sessionImpl = (SessionImplementor) session; + EntityEntry ee = sessionImpl.persistenceContext.getEntry(target) - @Override - D refresh(D instance) { - hibernateTemplate.refresh(instance) - return instance - } + if (ee && ee.status == Status.READ_ONLY) { + Object actualTarget = target + if (target instanceof HibernateProxy) { + actualTarget = ((HibernateProxy)target).hibernateLazyInitializer.implementation + } - @Override - D save(D instance) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", EMPTY_ARRAY) + session.setReadOnly actualTarget, false + session.flushMode = FlushMode.AUTO + incrementVersion target + } + } + return null } - else { - return super.save(instance) - } - } - - D save(D instance, boolean validate) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", [validate] as Object[]) - } - else { - return super.save(instance, validate) - } - } - - @Override - D merge(D instance) { - if (mergeMethod) { - return (D)mergeMethod.invoke(instance, "merge", EMPTY_ARRAY) - } - else { - return super.merge(instance) - } - } - - @Override - D merge(D instance, Map params) { - if (mergeMethod) { - return (D)mergeMethod.invoke(instance, "merge", [params] as Object[]) - } - else { - return super.merge(instance, params) - } - } - - @Override - D save(D instance, Map params) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", [params] as Object[]) - } - return super.save(instance, params) - } - - @Override - D attach(D instance) { - hibernateTemplate.lock(instance, LockMode.NONE) - return instance - } - - @Override - void discard(D instance) { - hibernateTemplate.evict instance - } - - @Override - void delete(D instance) { - boolean flush = shouldFlush() - try { - instanceApiHelper.delete instance, flush - } - catch (DataAccessException e) { - handleDataAccessException(hibernateTemplate, e) - } - } - - @Override - void delete(D instance, Map params) { - boolean flush = shouldFlush(params) - try { - instanceApiHelper.delete instance, flush - } - catch (DataAccessException e) { - handleDataAccessException(hibernateTemplate, e) - } - } - - @Override - boolean instanceOf(D instance, Class cls) { - if (instance instanceof HibernateProxy) { - return GrailsHibernateUtil.unwrapProxy(instance) in cls - } - return instance in cls - } - - @Override - boolean isAttached(D instance) { - hibernateTemplate.contains instance } protected EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) { @@ -258,22 +170,4 @@ entry } - /** - * Session should no longer be flushed after a data access exception occurs (such a constriant violation) - */ - protected void handleDataAccessException(GrailsHibernateTemplate template, DataAccessException e) { - try { - instanceApiHelper.setFlushModeManual() - } - finally { - throw e - } - } - - protected boolean shouldFlush(Map map = [:]) { - if (map?.containsKey('flush')) { - return Boolean.TRUE == map.flush - } - return config?.autoFlush instanceof Boolean ? config.autoFlush : false - } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy index ba5e9fb..573e7b0 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -15,32 +15,21 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass import grails.orm.HibernateCriteriaBuilder +import grails.orm.PagedResultList +import groovy.transform.CompileDynamic import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.orm.hibernate.cfg.CompositeIdentity -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteQueryPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteUpdatePersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ListPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.MergePersistentMethod -import org.grails.datastore.gorm.GormStaticApi +import org.codehaus.groovy.grails.orm.hibernate.query.GrailsHibernateQueryUtils +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.query.api.BuildableCriteria as GrailsCriteria import org.hibernate.Criteria import org.hibernate.LockMode import org.hibernate.Session import org.hibernate.SessionFactory -import org.hibernate.criterion.Projections -import org.hibernate.criterion.Restrictions -import org.hibernate.transform.DistinctRootEntityResultTransformer import org.springframework.core.convert.ConversionService import org.springframework.orm.hibernate3.HibernateCallback import org.springframework.orm.hibernate3.HibernateTemplate @@ -56,150 +45,66 @@ * @since 1.0 */ @CompileStatic -class HibernateGormStaticApi<D> extends GormStaticApi<D> { - protected static final EMPTY_ARRAY = [] as Object[] - +class HibernateGormStaticApi<D> extends AbstractHibernateGormStaticApi<D> { protected GrailsHibernateTemplate hibernateTemplate protected SessionFactory sessionFactory protected ConversionService conversionService protected Class identityType - protected ListPersistentMethod listMethod - protected FindAllPersistentMethod findAllMethod - protected FindPersistentMethod findMethod - protected ExecuteQueryPersistentMethod executeQueryMethod - protected ExecuteUpdatePersistentMethod executeUpdateMethod - protected MergePersistentMethod mergeMethod protected ClassLoader classLoader protected GrailsApplication grailsApplication - protected GrailsDomainBinder grailsDomainBinder = new GrailsDomainBinder() + private HibernateGormInstanceApi<D> instanceApi protected int defaultFlushMode HibernateGormStaticApi(Class<D> persistentClass, HibernateDatastore datastore, List<FinderMethod> finders, ClassLoader classLoader, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore, finders, transactionManager) + super(persistentClass, datastore, finders, transactionManager, null) this.classLoader = classLoader sessionFactory = datastore.getSessionFactory() conversionService = datastore.mappingContext.conversionService identityType = persistentEntity.identity?.type - def mappingContext = datastore.mappingContext grailsApplication = datastore.getGrailsApplication() if (grailsApplication != null) { GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.name) identityType = domainClass.identifier?.type - mergeMethod = new MergePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) - listMethod = new ListPersistentMethod(grailsApplication, sessionFactory, classLoader, mappingContext.conversionService, datastore.getDefaultFlushMode()) hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication, datastore.getDefaultFlushMode()) } else { hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) hibernateTemplate.setFlushMode(datastore.getDefaultFlushMode()) } - + super.hibernateTemplate = hibernateTemplate + this.defaultFlushMode = datastore.getDefaultFlushMode() - executeQueryMethod = new ExecuteQueryPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) - executeUpdateMethod = new ExecuteUpdatePersistentMethod(sessionFactory, classLoader, grailsApplication, datastore.getDefaultFlushMode()) - findMethod = new FindPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) - findAllMethod = new FindAllPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) + instanceApi = new HibernateGormInstanceApi<>(persistentClass, datastore, classLoader) } - -// /** -// * Property missing handling used to relay property access onto target entity for named queries etc. -// * -// * @param property The name of the property -// */ -// @CompileStatic(TypeCheckingMode.SKIP) -// def propertyMissing(String property) { -// if(persistentClass.hasProperty(property)) { -// return this.persistentClass."$property" -// } -// else { -// throw new MissingPropertyException(property, HibernateGormStaticApi) -// } -// } - @Override - D get(Serializable id) { - if (id || (id instanceof Number)) { - id = convertIdentifier(id) - D result = (D)hibernateTemplate.get((Class)persistentClass, id) - return (D)GrailsHibernateUtil.unwrapIfProxy(result) + List<D> list(Map params = Collections.emptyMap()) { + hibernateTemplate.execute { Session session -> + Criteria c = session.createCriteria(persistentEntity.javaClass) + hibernateTemplate.applySettings c + + params = params ? new HashMap(params) : Collections.emptyMap() + setResultTransformer(c) + if(params.containsKey(DynamicFinder.ARGUMENT_MAX)) { + + c.setMaxResults(Integer.MAX_VALUE) + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, c, params, datastore.mappingContext.conversionService, true) + return new PagedResultList(hibernateTemplate, c) + } + else { + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, c, params, datastore.mappingContext.conversionService, true) + return c.list() + } } } - protected Serializable convertIdentifier(Serializable id) { - (Serializable)HibernateUtils.convertValueToType(id, identityType, conversionService) - } - - @Override - D read(Serializable id) { - if (id == null) { - return null - } - - hibernateTemplate.execute({ Session session -> - def o = get(id) - if (o && session.contains(o)) { - session.setReadOnly(o, true) - } - return o - } as HibernateCallback) - } - - @Override - D load(Serializable id) { - id = convertIdentifier(id) - if (id != null) { - return hibernateTemplate.load((Class)persistentClass, id) - } - } - - @Override - List<D> getAll() { - (List<D>)hibernateTemplate.execute({ Session session -> - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.list() - } as HibernateCallback) - } - - List<D> getAll(List ids) { - getAllInternal(ids) - } - - List<D> getAll(Long... ids) { - getAllInternal(ids as List) - } - - @Override - List<D> getAll(Serializable... ids) { - getAllInternal(ids as List) - } - - protected List getAllInternal(List ids) { - if (!ids) return [] - - ids = ids.collect { convertIdentifier((Serializable)it) } - - (List)hibernateTemplate.execute({Session session -> - def criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - def identityName = persistentEntity.identity.name - criteria.add(Restrictions.'in'(identityName, ids)) - def results = criteria.list() - def idsMap = [:] - for (object in results) { - idsMap[object[identityName]] = object - } - results.clear() - for (id in ids) { - results << idsMap[id] - } - results - } as HibernateCallback) + @CompileDynamic + protected void setResultTransformer(Criteria c) { + c.resultTransformer = Criteria.DISTINCT_ROOT_ENTITY } @Override @@ -207,7 +112,6 @@ def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) builder.grailsApplication = grailsApplication builder.conversionService = conversionService - builder.defaultFlushMode = defaultFlushMode builder } @@ -218,250 +122,8 @@ } @Override - D merge(o) { - (D)mergeMethod.invoke(o, "merge", [] as Object[]) - } - - @Override - Integer count() { - (Integer)hibernateTemplate.execute({Session session -> - def criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.setProjection(Projections.rowCount()) - def num = criteria.uniqueResult() - num == null ? 0 : num - } as HibernateCallback) - } - - @Override - boolean exists(Serializable id) { - id = convertIdentifier(id) - hibernateTemplate.execute({ Session session -> - Criteria criteria = session.createCriteria(persistentEntity.javaClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.idEq(id)) - .setProjection(Projections.rowCount()) - .uniqueResult() - } as HibernateCallback) == 1 - } - - @Override - List<D> list(Map params) { - (List<D>)listMethod.invoke(persistentClass, "list", [params] as Object[]) - } - - @Override - List<D> list() { - (List<D>)listMethod.invoke(persistentClass, "list", EMPTY_ARRAY) - } - - @Override - List<D> findAll(example, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [example, args] as Object[]) - } - - @Override - D find(example, Map args) { - (D)findMethod.invoke(persistentClass, "find", [example, args] as Object[]) - } - - D first(Map m) { - def entityMapping = grailsDomainBinder.getMapping(persistentEntity.javaClass) - if (entityMapping?.identity instanceof CompositeIdentity) { - throw new UnsupportedOperationException('The first() method is not supported for domain classes that have composite keys.') - } - super.first(m) - } - - D last(Map m) { - def entityMapping = grailsDomainBinder.getMapping(persistentEntity.javaClass) - if (entityMapping?.identity instanceof CompositeIdentity) { - throw new UnsupportedOperationException('The last() method is not supported for domain classes that have composite keys.') - } - super.last(m) - } - - /** - * Finds a single result for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @return A single result or null - * - * @deprecated Use Book.find('..', [foo:'bar], [max:10]) instead - */ - @Deprecated - D find(String query, Map args, Integer max) { - (D)findMethod.invoke(persistentClass, "find", [query, args, max] as Object[]) - } - - /** - * Finds a single result for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @param offset The offset - * @return A single result or null - * - * @deprecated Use Book.find('..', [foo:'bar], [max:10, offset:5]) instead - */ - @Deprecated - D find(String query, Map args, Integer max, Integer offset) { - (D)findMethod.invoke(persistentClass, "find", [query, args, max, offset] as Object[]) - } - - /** - * Finds a single result for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A single result or null - * - * @deprecated Use Book.find('..', [max:10]) instead - */ - @Deprecated - D find(String query, Integer max) { - (D)findMethod.invoke(persistentClass, "find", [query, max] as Object[]) - } - - /** - * Finds a single result for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @param offset The offset to use - * @return A single result or null - * - * @deprecated Use Book.find('..', [max:10, offset:5]) instead - */ - @Deprecated - D find(String query, Integer max, Integer offset) { - (D)findMethod.invoke(persistentClass, "find", [query, max, offset] as Object[]) - } - - /** - * Finds a list of results for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [foo:'bar], [max:10]) instead - */ - @Deprecated - List<D> findAll(String query, Map args, Integer max) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args, max] as Object[]) - } - - /** - * Finds a list of results for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @param offset The offset - * - * @return A list of results - * - * @deprecated Use findAll('..', [foo:'bar], [max:10, offset:5]) instead - */ - @Deprecated - List<D> findAll(String query, Map args, Integer max, Integer offset) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args, max, offset] as Object[]) - } - - /** - * Finds a list of results for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [max:10]) instead - */ - @Deprecated - List<D> findAll(String query, Integer max) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, max] as Object[]) - } - - /** - * Finds a list of results for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [max:10, offset:5]) instead - */ - @Deprecated - List<D> findAll(String query, Integer max, Integer offset) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, max, offset] as Object[]) - } - - @Override - List<D> findAllWhere(Map queryMap, Map args) { - if (!queryMap) return null - (List<D>)hibernateTemplate.execute({Session session -> - Map<String, Object> processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) - List<String> nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) - } - criteria.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE) - criteria.list() - } as HibernateCallback) - } - - @Override - D findWhere(Map queryMap, Map args) { - if (!queryMap) return null - (D)hibernateTemplate.execute({Session session -> - Map<String, Object> processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) - List<String> nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) - } - criteria.setMaxResults(1) - GrailsHibernateUtil.unwrapIfProxy(criteria.uniqueResult()) - } as HibernateCallback) - } - - protected Map filterQueryArgumentMap(Map query) { - def queryArgs = [:] - for (entry in query.entrySet()) { - if (entry.value instanceof CharSequence) { - queryArgs[entry.key] = entry.value.toString() - } - else { - queryArgs[entry.key] = entry.value - } - } - return queryArgs - } - - protected List<String> removeNullNames(Map query) { - List<String> nullNames = [] - Set<String> allNames = new HashSet(query.keySet()) - for (String name in allNames) { - if (query[name] == null) { - query.remove name - nullNames << name - } - } - nullNames + D merge( D o ) { + instanceApi.merge(o) } @Override @@ -475,6 +137,44 @@ } @Override + Integer executeUpdate(String query, Map params, Map args) { + def template = hibernateTemplate + return (Integer) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + SessionFactoryUtils.applyTransactionTimeout q, template.sessionFactory + + + populateQueryArguments(q, params) + populateQueryArguments(q, args) + populateQueryWithNamedArguments(q, params) + + return q.executeUpdate() + } + } + + @Override + Integer executeUpdate(String query, Collection params, Map args) { + def template = hibernateTemplate + return (Integer) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + SessionFactoryUtils.applyTransactionTimeout q, template.sessionFactory + + params.eachWithIndex { val, int i -> + if (val instanceof CharSequence) { + q.setParameter i, val.toString() + } + else { + q.setParameter i, val + } + } + populateQueryArguments(q, args) + return q.executeUpdate() + } + } + + @Override def withNewSession(Closure callable) { HibernateTemplate template = new GrailsHibernateTemplate(sessionFactory, grailsApplication, defaultFlushMode) template.setExposeNativeSession(false) @@ -511,112 +211,4 @@ } } - @Override - List<D> executeQuery(String query) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query] as Object[]) - } - - List<D> executeQuery(String query, arg) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, arg] as Object[]) - } - - @Override - List<D> executeQuery(String query, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, args] as Object[]) - } - - @Override - List<D> executeQuery(String query, Map params, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - List<D> executeQuery(String query, Collection params) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params] as Object[]) - } - - @Override - List<D> executeQuery(String query, Collection params, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - Integer executeUpdate(String query) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query] as Object[]) - } - - @Override - Integer executeUpdate(String query, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, args] as Object[]) - } - - @Override - Integer executeUpdate(String query, Map params, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params, args] as Object[]) - } - - @Override - Integer executeUpdate(String query, Collection params) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params] as Object[]) - } - - @Override - Integer executeUpdate(String query, Collection params, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params, args] as Object[]) - } - - @Override - D find(String query) { - (D)findMethod.invoke(persistentClass, "find", [query] as Object[]) - } - - D find(String query, Object[] params) { - (D)findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, args] as Object[]) - } - - @Override - D find(String query, Map params, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - Object find(String query, Collection params) { - findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Collection params, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - List<D> findAll(String query) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query] as Object[]) - } - - @Override - List<D> findAll(String query, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args] as Object[]) - } - - @Override - List<D> findAll(String query, Map params, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - List<D> findAll(String query, Collection params) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params] as Object[]) - } - - @Override - List<D> findAll(String query, Collection params, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy index 4fcb082..6881ddf 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy
@@ -17,22 +17,10 @@ import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod - @CompileStatic class HibernateGormValidationApi<D> extends AbstractHibernateGormValidationApi<D> { - ValidatePersistentMethod validateMethod - HibernateGormValidationApi(Class<D> persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - def grailsApplication = datastore.grailsApplication - if (grailsApplication) { - def validator = mappingContext.getEntityValidator(mappingContext.getPersistentEntity(persistentClass.name)) - validateMethod = new ValidatePersistentMethod(datastore.getSessionFactory(), - classLoader, grailsApplication, validator, datastore) - } } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java index 1e2ba28..dc9f96a 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java
@@ -21,10 +21,10 @@ import javax.persistence.FlushModeType; -import org.codehaus.groovy.grails.commons.GrailsApplication; +import grails.core.GrailsApplication; +import grails.core.support.proxy.ProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.query.HibernateQuery; -import org.codehaus.groovy.grails.support.proxy.ProxyHandler; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java index 7c8c9c1..6ed1806 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java
@@ -14,20 +14,25 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.GrailsApplication; +import grails.core.GrailsClass; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import groovy.lang.Closure; import groovy.util.Eval; import java.util.HashSet; +import java.util.Properties; import java.util.Set; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwarePojoEntityTuplizer; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Mappings; +import org.hibernate.cfg.Settings; /** * Creates runtime configuration mapping for the Grails domain classes @@ -123,6 +128,20 @@ } } } + + @Override + public Settings buildSettings() { + Settings settings = super.buildSettings(); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + + @Override + public Settings buildSettings(Properties props) throws HibernateException { + Settings settings = super.buildSettings(props); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } @Override protected void reset() {
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java index a966725..693fc0e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java
@@ -14,25 +14,23 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; +import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwarePojoEntityTuplizer; +import org.grails.core.artefact.AnnotationDomainClassArtefactHandler; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.ImprovedNamingStrategy; -import org.hibernate.cfg.Mappings; -import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.*; import org.hibernate.engine.FilterDefinition; import org.hibernate.mapping.JoinedSubclass; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import java.util.*; /** * Allows configuring Grails' hibernate support to work in conjunction with Hibernate's annotation @@ -63,6 +61,9 @@ if (shouldMapWithGorm(domainClass)) { domainClasses.add(domainClass); } + else { + addAnnotatedClass(domainClass.getClazz()); + } return this; } @@ -142,6 +143,20 @@ return sessionFactory; } + @Override + public Settings buildSettings() { + Settings settings = super.buildSettings(); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + + @Override + public Settings buildSettings(Properties props) throws HibernateException { + Settings settings = super.buildSettings(props); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + /** * Overrides the default behaviour to including binding of Grails domain classes. */
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java index a6c4dc0..4d033fd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java
@@ -17,13 +17,13 @@ import java.util.Arrays; import java.util.List; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.validation.ConstrainedProperty; +import grails.validation.Constraint; import org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareJoinedSubclassEntityPersister; import org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityPersister; import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -import org.codehaus.groovy.grails.validation.Constraint; import org.hibernate.mapping.Column; import org.hibernate.mapping.Table;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java index 1bbe7eb..7ad663e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java
@@ -14,19 +14,25 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.GrailsApplication; +import grails.core.GrailsClass; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import grails.util.CollectionUtils; +import grails.util.GrailsClassUtils; import grails.util.Holders; import groovy.lang.GroovyObject; import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateDomainClass; import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.grails.core.DefaultGrailsDomainClass; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.hibernate.*; import org.hibernate.criterion.Order; import org.hibernate.engine.EntityEntry; @@ -246,7 +252,7 @@ * @param c The criteria instance * @param argMap The arguments map * - * @deprecated Use {@link #populateArgumentsForCriteria(org.codehaus.groovy.grails.commons.GrailsApplication, Class, org.hibernate.Criteria, java.util.Map)} instead + * @deprecated Use {@link #populateArgumentsForCriteria(GrailsApplication, Class, org.hibernate.Criteria, java.util.Map)} instead */ @Deprecated @SuppressWarnings("rawtypes")
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy index 61cc81b..750bee8 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy
@@ -16,23 +16,24 @@ package org.codehaus.groovy.grails.orm.hibernate.cfg import grails.artefact.Enhanced +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.util.GrailsClassUtils +import grails.util.GrailsMetaClassUtils import grails.util.GrailsNameUtils import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsClassUtils -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore import org.codehaus.groovy.grails.orm.hibernate.HibernateGormEnhancer import org.codehaus.groovy.grails.orm.hibernate.HibernateGormInstanceApi import org.codehaus.groovy.grails.orm.hibernate.HibernateGormStaticApi import org.codehaus.groovy.grails.orm.hibernate.HibernateGormValidationApi import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor +import org.codehaus.groovy.grails.orm.hibernate.support.HibernateRuntimeUtils import org.codehaus.groovy.runtime.InvokerHelper -import org.codehaus.groovy.runtime.StringGroovyMethods +import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity @@ -185,13 +186,14 @@ // http://jira.codehaus.org/browse/GROOVY-6138 prevents using CompileStatic for this method @CompileStatic(TypeCheckingMode.SKIP) static void enhanceProxyClass(Class proxyClass) { - MetaMethod grailsEnhancedMetaMethod = proxyClass.metaClass.getStaticMetaMethod("grailsEnhanced", (Class[])null) + MetaClass mc = GrailsMetaClassUtils.getExpandoMetaClass(proxyClass) + MetaMethod grailsEnhancedMetaMethod = mc.getStaticMetaMethod("grailsEnhanced", (Class[])null) if (grailsEnhancedMetaMethod != null && grailsEnhancedMetaMethod.invoke(proxyClass, null) == proxyClass) { return } - MetaClass mc = (MetaClass)InvokerHelper.getMetaClass(proxyClass) - MetaClass superMc = InvokerHelper.getMetaClass(proxyClass.getSuperclass()) + MetaClass superMc = GrailsMetaClassUtils.getExpandoMetaClass(proxyClass.getSuperclass()) + // hasProperty registerMetaMethod(mc, 'hasProperty', { String name -> @@ -328,38 +330,6 @@ } static Object convertValueToType(Object passedValue, Class targetType, ConversionService conversionService) { - // workaround for GROOVY-6127, do not assign directly in parameters before it's fixed - Object value = passedValue - if(targetType != null && value != null && !(value in targetType)) { - if (value instanceof CharSequence) { - value = value.toString() - if(value in targetType) { - return value - } - } - try { - if (value instanceof Number && (targetType==Long || targetType==Integer)) { - if(targetType == Long) { - value = ((Number)value).toLong() - } else { - value = ((Number)value).toInteger() - } - } else if (value instanceof String && targetType in Number) { - String strValue = value.trim() - if(targetType == Long) { - value = Long.parseLong(strValue) - } else if (targetType == Integer) { - value = Integer.parseInt(strValue) - } else { - value = StringGroovyMethods.asType(strValue, targetType) - } - } else { - value = conversionService.convert(value, targetType) - } - } catch (e) { - // ignore - } - } - return value + HibernateRuntimeUtils.convertValueToType(passedValue, targetType, conversionService) } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java deleted file mode 100644 index 6d575a7..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java +++ /dev/null
@@ -1,548 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.RlikeExpression; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; -import groovy.lang.Range; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; -import org.hibernate.Criteria; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.CriteriaQuery; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; -import org.hibernate.engine.TypedValue; -import org.springframework.beans.TypeMismatchException; -import org.springframework.core.convert.ConversionService; -import org.springframework.util.Assert; - -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public abstract class AbstractClausedStaticPersistentMethod extends AbstractStaticPersistentMethod { - - protected static final Log LOG = LogFactory.getLog(AbstractClausedStaticPersistentMethod.class); - - /** - * @author Graeme Rocher - */ - protected abstract static class GrailsMethodExpression { - protected static final String LESS_THAN = "LessThan"; - protected static final String LESS_THAN_OR_EQUAL = "LessThanEquals"; - protected static final String GREATER_THAN = "GreaterThan"; - protected static final String GREATER_THAN_OR_EQUAL = "GreaterThanEquals"; - protected static final String LIKE = "Like"; - protected static final String ILIKE = "Ilike"; - protected static final String RLIKE = "Rlike"; - protected static final String BETWEEN = "Between"; - protected static final String IN_LIST= "InList"; - protected static final String IS_NOT_NULL = "IsNotNull"; - protected static final String IS_NULL = "IsNull"; - protected static final String NOT = "Not"; - protected static final String EQUAL = "Equal"; - protected static final String NOT_EQUAL = "NotEqual"; - protected static final String IN_RANGE = "InRange"; - - protected String propertyName; - protected Object[] arguments; - protected int argumentsRequired; - protected boolean negation; - protected String type; - protected Class<?> targetClass; - private GrailsApplication application; - protected final ConversionService conversionService; - - /** - * Used as an indication that an expression will return no results, so stop processing and return nothing. - */ - static final Criterion FORCE_NO_RESULTS = new Criterion() { - private static final long serialVersionUID = 1L; - public TypedValue[] getTypedValues(Criteria c, CriteriaQuery q) { return null; } - public String toSqlString(Criteria c, CriteriaQuery q) { return null; } - }; - - GrailsMethodExpression(GrailsApplication application, Class<?> targetClass, - String propertyName, String type, int argumentsRequired, boolean negation, ConversionService conversionService) { - this.application = application; - this.targetClass = targetClass; - this.propertyName = propertyName; - this.type = type; - this.argumentsRequired = argumentsRequired; - this.negation = negation; - this.conversionService = conversionService; - } - - GrailsMethodExpression(GrailsApplication application, Class<?> targetClass, - String queryParameter, String type, int argumentsRequired, ConversionService conversionService) { - this(application, targetClass, calcPropertyName(queryParameter, type), type, - argumentsRequired, isNegation(queryParameter, type), conversionService); - } - - public String getPropertyName() { - return propertyName; - } - - public Object[] getArguments() { - Object[] copy = new Object[arguments.length]; - System.arraycopy(arguments, 0, copy, 0, arguments.length); - return copy; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("[GrailsMethodExpression] "); - buf.append(propertyName) - .append(" ") - .append(type) - .append(" "); - - for (int i = 0; i < arguments.length; i++) { - buf.append(arguments[i]); - if (i != arguments.length) { - buf.append(" and "); - } - } - return buf.toString(); - } - - @SuppressWarnings("unchecked") - protected void setArguments(Object[] args) throws IllegalArgumentException { - if (args.length != argumentsRequired) { - throw new IllegalArgumentException("Method expression '" + type + "' requires " + - argumentsRequired + " arguments"); - } - - GrailsDomainClass dc = (GrailsDomainClass)application.getArtefact( - DomainClassArtefactHandler.TYPE, targetClass.getName()); - GrailsDomainClassProperty prop = dc.getPropertyByName(propertyName); - - if (prop == null) { - throw new IllegalArgumentException("Property " + propertyName + - " doesn't exist for method expression '"+ type + "'"); - } - - for (int i = 0; i < args.length; i++) { - Object currentArg = args[i]; - if (currentArg == null) continue; - // convert GStrings to strings - if (prop.getType() == String.class && (currentArg instanceof CharSequence)) { - args[i] = currentArg.toString(); - } - else if (!prop.getType().isAssignableFrom(currentArg.getClass()) && !(GrailsClassUtils.isMatchBetweenPrimativeAndWrapperTypes(prop.getType(), currentArg.getClass()))) { - try { - if (type.equals(IN_LIST)) { - if(currentArg instanceof Collection) { - currentArg = convertArgumentList(prop, (Collection)currentArg); - } - args[i] = conversionService.convert(currentArg, Collection.class); - } - else { - args[i] = conversionService.convert(currentArg, prop.getType()); - } - } - catch (TypeMismatchException tme) { - // if we cannot perform direct conversion and argument is subclass of Number - // we can try to convert it through its String representation - if (Number.class.isAssignableFrom(currentArg.getClass())) { - try { - args[i] = conversionService.convert(currentArg.toString(), prop.getType()); - } - catch(TypeMismatchException tme1) { - throw new IllegalArgumentException("Cannot convert value " + currentArg + " of property '"+propertyName+"' to required type " + prop.getType() + ": " + tme1.getMessage()); - } - } - else { - throw new IllegalArgumentException("Cannot convert value " + currentArg + " of property '"+propertyName+"' to required type " + prop.getType()); - } - } - } - else if(type.equals(IN_LIST) && (currentArg instanceof Collection)) { - currentArg = convertArgumentList(prop, (Collection) currentArg); - } - } - - arguments = args; - } - - protected List convertArgumentList(GrailsDomainClassProperty prop, Collection argList) { - List convertedList = new ArrayList(argList.size()); - for (Object item : argList) { - if(item instanceof CharSequence) { - item = item.toString(); - } - convertedList.add(conversionService.convert(item, prop.getType())); - } - return convertedList; - } - - abstract Criterion createCriterion(); - - protected Criterion getCriterion() { - Assert.notNull(arguments, "Parameters array must be set before retrieving Criterion"); - return negation ? Restrictions.not(createCriterion()) : createCriterion(); - } - - protected static GrailsMethodExpression create(final GrailsApplication application, - Class<?> clazz, String queryParameter, ConversionService conversionService) { - - if (queryParameter.endsWith(LESS_THAN_OR_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LESS_THAN_OR_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.le(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(LESS_THAN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LESS_THAN, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.lt(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(GREATER_THAN_OR_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, GREATER_THAN_OR_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.ge(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(GREATER_THAN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, GREATER_THAN, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.gt(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(LIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.like(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(ILIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, ILIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.ilike(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(RLIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, RLIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return new RlikeExpression(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(IS_NOT_NULL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IS_NOT_NULL, 0, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.isNotNull(propertyName); - } - }; - } - - if (queryParameter.endsWith(IS_NULL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IS_NULL, 0, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.isNull(propertyName); - } - }; - } - - if (queryParameter.endsWith(BETWEEN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, BETWEEN, 2, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.between(propertyName,arguments[0], arguments[1]); - } - }; - } - - if (queryParameter.endsWith(IN_LIST)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IN_LIST, 1, conversionService) { - @SuppressWarnings("rawtypes") - @Override - Criterion createCriterion() { - Collection collection = (Collection)arguments[0]; - if (collection == null || collection.isEmpty()) { - return FORCE_NO_RESULTS; - } - return Restrictions.in(propertyName, collection); - } - }; - } - - if (queryParameter.endsWith(NOT_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, NOT_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNotNull(propertyName); - return Restrictions.ne(propertyName,arguments[0]); - } - }; - } - - if (queryParameter.endsWith(IN_RANGE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IN_RANGE, 1, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.between(propertyName, arguments[0], arguments[1]); - } - @Override - protected void setArguments(Object[] args) throws IllegalArgumentException { - if (args != null && args.length > 0 && args[0] instanceof Range) { - Range<?> range = (Range<?>) args[0]; - args = new Object[] { range.getFrom(), range.getTo() }; - argumentsRequired = 2; - } - super.setArguments(args); - } - }; - } - - return new GrailsMethodExpression(application, clazz, - calcPropertyName(queryParameter, null), - EQUAL, 1, isNegation(queryParameter, EQUAL), conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.eq(propertyName,arguments[0]); - } - }; - } - - private static boolean isNegation(String queryParameter, String clause) { - String propName; - if (clause != null && !clause.equals(EQUAL)) { - int i = queryParameter.indexOf(clause); - propName = queryParameter.substring(0,i); - } - else { - propName = queryParameter; - } - return propName.endsWith(NOT); - } - - private static String calcPropertyName(String queryParameter, String clause) { - String propName; - if (clause != null && !clause.equals(EQUAL)) { - int i = queryParameter.indexOf(clause); - propName = queryParameter.substring(0,i); - } - else { - propName = queryParameter; - } - if (propName.endsWith(NOT)) { - int i = propName.lastIndexOf(NOT); - propName = propName.substring(0, i); - } - return propName.substring(0,1).toLowerCase(Locale.ENGLISH) + propName.substring(1); - } - } - - private final String[] operators; - private final Pattern[] operatorPatterns; - protected final ConversionService conversionService; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - * @param pattern - * @param operators - */ - public AbstractClausedStaticPersistentMethod(GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader, Pattern pattern, String[] operators, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, pattern, application, defaultFlushMode); - this.operators = operators; - operatorPatterns = new Pattern[operators.length]; - for (int i = 0; i < operators.length; i++) { - operatorPatterns[i] = Pattern.compile("(\\w+)("+operators[i]+")(\\p{Upper})(\\w+)"); - } - this.conversionService = conversionService; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod#doInvokeInternal(java.lang.Class, java.lang.String, java.lang.Object[]) - */ - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, - Closure additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz, methodName, null, additionalCriteria, arguments); - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz, methodName, additionalCriteria,null, arguments); - } - - protected Object doInvokeInternal(Class<?> clazz, String methodName, DetachedCriteria<?> detachedCriteria, Closure<?> additionalCriteria, Object[] arguments) { - List<GrailsMethodExpression> expressions = new ArrayList<GrailsMethodExpression>(); - if (arguments == null) arguments = new Object[0]; - Matcher match = super.getPattern().matcher(methodName); - // find match - match.find(); - - String[] queryParameters; - int totalRequiredArguments = 0; - // get the sequence clauses - final String querySequence; - int groupCount = match.groupCount(); - if (groupCount == 6) { - String booleanProperty = match.group(3); - if (booleanProperty == null) { - booleanProperty = match.group(6); - querySequence = null; - } - else { - querySequence = match.group(5); - } - Boolean arg = Boolean.TRUE; - if (booleanProperty.matches("Not[A-Z].*")) { - booleanProperty = booleanProperty.substring(3); - arg = Boolean.FALSE; - } - GrailsMethodExpression booleanExpression = GrailsMethodExpression.create( - application, clazz, booleanProperty, conversionService); - booleanExpression.setArguments(new Object[]{arg}); - expressions.add(booleanExpression); - } - else { - querySequence = match.group(2); - } - // if it contains operator and split - boolean containsOperator = false; - String operatorInUse = null; - - if (querySequence != null) { - for (int i = 0; i < operators.length; i++) { - Matcher currentMatcher = operatorPatterns[i].matcher(querySequence); - if (currentMatcher.find()) { - containsOperator = true; - operatorInUse = operators[i]; - - queryParameters = querySequence.split(operatorInUse); - - // loop through query parameters and create expressions - // calculating the number of arguments required for the expression - int argumentCursor = 0; - for (String queryParameter : queryParameters) { - GrailsMethodExpression currentExpression = GrailsMethodExpression.create( - application, clazz, queryParameter, conversionService); - totalRequiredArguments += currentExpression.argumentsRequired; - // populate the arguments into the GrailsExpression from the argument list - Object[] currentArguments = new Object[currentExpression.argumentsRequired]; - if ((argumentCursor + currentExpression.argumentsRequired) > arguments.length) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - for (int k = 0; k < currentExpression.argumentsRequired; k++, argumentCursor++) { - currentArguments[k] = arguments[argumentCursor]; - } - try { - currentExpression.setArguments(currentArguments); - } - catch (IllegalArgumentException iae) { - LOG.debug(iae.getMessage(), iae); - throw new MissingMethodException(methodName, clazz, arguments); - } - // add to list of expressions - expressions.add(currentExpression); - } - break; - } - } - } - - // otherwise there is only one expression - if (!containsOperator && querySequence != null) { - GrailsMethodExpression solo = GrailsMethodExpression.create(application, clazz, querySequence, conversionService); - - if (solo.argumentsRequired > arguments.length) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - totalRequiredArguments += solo.argumentsRequired; - Object[] soloArgs = new Object[solo.argumentsRequired]; - - System.arraycopy(arguments, 0, soloArgs, 0, solo.argumentsRequired); - try { - solo.setArguments(soloArgs); - } - catch (IllegalArgumentException iae) { - LOG.debug(iae.getMessage(), iae); - throw new MissingMethodException(methodName,clazz,arguments); - } - expressions.add(solo); - } - - // if the total of all the arguments necessary does not equal the number of arguments throw exception - if (totalRequiredArguments > arguments.length) { - throw new MissingMethodException(methodName,clazz,arguments); - } - - // calculate the remaining arguments - Object[] remainingArguments = new Object[arguments.length - totalRequiredArguments]; - if (remainingArguments.length > 0) { - for (int i = 0, j = totalRequiredArguments; i < remainingArguments.length; i++,j++) { - remainingArguments[i] = arguments[j]; - } - } - - if (LOG.isTraceEnabled()) { - LOG.trace("Calculated expressions: " + expressions); - } - - return doInvokeInternalWithExpressions(clazz, methodName, remainingArguments, expressions, operatorInUse, detachedCriteria, additionalCriteria); - } - - @SuppressWarnings("rawtypes") - protected abstract Object doInvokeInternalWithExpressions(Class clazz, String methodName, Object[] arguments, List expressions, String operatorInUse, DetachedCriteria detachedCriteria, Closure additionalCriteria); -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java deleted file mode 100644 index 1dd3b6d..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java +++ /dev/null
@@ -1,117 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.ValidationErrors; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.metaclass.AbstractDynamicMethodInvocation; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; -import org.springframework.validation.FieldError; - -/** - * @author Steven Devijver - */ -public abstract class AbstractDynamicPersistentMethod extends AbstractDynamicMethodInvocation { - - public static final String ERRORS_PROPERTY = "errors"; - - private ClassLoader classLoader; - private HibernateTemplate hibernateTemplate; - GrailsApplication application; - int defaultFlushMode; - - public AbstractDynamicPersistentMethod(Pattern pattern, SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, int defaultFlushMode) { - super(pattern); - Assert.notNull(sessionFactory, "Session factory is required!"); - this.classLoader = classLoader; - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.application = application; - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, application, defaultFlushMode); - } - - protected HibernateTemplate getHibernateTemplate() { - return hibernateTemplate; - } - - @Override - public Object invoke(Object target, String methodName, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(target, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - protected abstract Object doInvokeInternal(Object target, Object[] arguments); - - /** - * This method will set the target object to read-only if it is contained with the Hibernate session, - * Preventing Hibernate dirty-checking from persisting the instance - * - * @param target The target object - */ - protected void setObjectToReadOnly(final Object target) { - GrailsHibernateUtil.setObjectToReadyOnly(target, getHibernateTemplate().getSessionFactory()); - } - - protected void setObjectToReadWrite(final Object target) { - GrailsHibernateUtil.setObjectToReadWrite(target, getHibernateTemplate().getSessionFactory()); - } - - /** - * Initializes the Errors property on target. The target will be assigned a new - * Errors property. If the target contains any binding errors, those binding - * errors will be copied in to the new Errors property. - * - * @param target object to initialize - * @return the new Errors object - */ - protected Errors setupErrorsProperty(Object target) { - MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - - ValidationErrors errors = new ValidationErrors(target); - - Errors originalErrors = (Errors) mc.getProperty(target, ERRORS_PROPERTY); - for (Object o : originalErrors.getFieldErrors()) { - FieldError fe = (FieldError)o; - if (fe.isBindingFailure()) { - errors.addError(new FieldError(fe.getObjectName(), - fe.getField(), - fe.getRejectedValue(), - fe.isBindingFailure(), - fe.getCodes(), - fe.getArguments(), - fe.getDefaultMessage())); - } - } - - mc.setProperty(target, ERRORS_PROPERTY, errors); - return errors; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java deleted file mode 100644 index 10d780e..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java +++ /dev/null
@@ -1,180 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.NonUniqueResultException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Restrictions; -import org.hibernate.impl.CriteriaImpl; -import org.springframework.orm.hibernate3.HibernateCallback; - -public abstract class AbstractFindByPersistentMethod extends AbstractClausedStaticPersistentMethod { - public static final String OPERATOR_OR = "Or"; - public static final String OPERATOR_AND = "And"; - public static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - private static final Map<String, Boolean> useLimitCache = new ConcurrentHashMap<String, Boolean>(); - - public AbstractFindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, - SessionFactory sessionFactory, ClassLoader classLoader, - Pattern pattern, String[] operators) { - super(application, sessionFactory, classLoader, pattern, operators, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternalWithExpressions(final Class clazz, String methodName, final Object[] arguments, final List expressions, String operatorInUse, final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - final String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = buildCriteria(session, detachedCriteria, additionalCriteria, clazz, arguments, operator, expressions); - - boolean useLimit = establishWhetherToUseLimit(clazz); - return getResult(crit, useLimit); - } - }); - } - - private boolean establishWhetherToUseLimit(Class<?> clazz) { - boolean useLimit = true; - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, clazz.getName()); - if (domainClass != null) { - Boolean aBoolean = useLimitCache.get(domainClass.getName()); - if (aBoolean != null) { - useLimit = aBoolean; - } - else { - - for (GrailsDomainClassProperty property : domainClass.getPersistentProperties()) { - if ((property.isOneToMany()||property.isManyToMany()) && property.getFetchMode() == GrailsDomainClassProperty.FETCH_EAGER) { - useLimit = false; - useLimitCache.put(domainClass.getName(), useLimit); - break; - } - } - } - } - return useLimit; - } - - protected Object getResult(Criteria crit) { - CriteriaImpl impl = (CriteriaImpl) crit; - String entityOrClassName = impl.getEntityOrClassName(); - GrailsClass domainClass = application.getArtefact(DomainClassArtefactHandler.TYPE, entityOrClassName); - boolean useLimit = establishWhetherToUseLimit(domainClass.getClazz()); - - return getResult(crit, useLimit); - } - - protected Object getResult(Criteria crit, boolean useLimit) { - if (useLimit) { - final List<?> list = crit.list(); - if (!list.isEmpty()) { - return GrailsHibernateUtil.unwrapIfProxy(list.get(0)); - } - } - else { - try { - return crit.uniqueResult(); - } catch (NonUniqueResultException e) { - return null; - } - } - return null; - } - - protected Criteria buildCriteria(Session session, DetachedCriteria<?> detachedCriteria, - Closure<?> additionalCriteria, Class<?> clazz, Object[] arguments, - String operator, List<?> expressions) { - Criteria crit = getCriteria(datastore, application, session, detachedCriteria, additionalCriteria, clazz); - - boolean useLimit = establishWhetherToUseLimit(clazz); - - if (arguments.length > 0) { - if (arguments[0] instanceof Map<?, ?>) { - Map<?, ?> argMap = (Map<?, ?>)arguments[0]; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argMap, conversionService); - if (!argMap.containsKey(GrailsHibernateUtil.ARGUMENT_FETCH)) { - if (useLimit) { - crit.setMaxResults(1); - } - } - } - else { - if (useLimit) { - crit.setMaxResults(1); - } - } - } - else { - if (useLimit) { - crit.setMaxResults(1); - } - } - - if (operator.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - GrailsMethodExpression expression = (GrailsMethodExpression) expressions.remove(0); - crit.add(expression.getCriterion()); - } - Disjunction dis = Restrictions.disjunction(); - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - crit.add(current.getCriterion()); - } - } - return crit; - } - - /** - * Indicates if the first expression in the query is a required boolean property and as such should - * be ANDed to the other expressions, not ORed. - * - * @return true if the first expression is a required boolean property, false otherwise - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByBooleanPropertyPersistentMethod - */ - protected boolean firstExpressionIsRequiredBoolean() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java deleted file mode 100644 index 2c3a202..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java +++ /dev/null
@@ -1,377 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.DeferredBindingActions; -import grails.validation.ValidationException; -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint; -import org.codehaus.groovy.grails.validation.CascadingValidator; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.InvalidPropertyException; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * Abstract class for different implementations that perform saving to implement. - * - * @author Graeme Rocher - * @since 0.3 - */ -public abstract class AbstractSavePersistentMethod extends AbstractDynamicPersistentMethod { - - private HibernateDatastore datastore; - private static final String ARGUMENT_VALIDATE = "validate"; - private static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; - private static final String ARGUMENT_FLUSH = "flush"; - private static final String ARGUMENT_INSERT = "insert"; - private static final String ARGUMENT_FAIL_ON_ERROR = "failOnError"; - private static final String FAIL_ON_ERROR_CONFIG_PROPERTY = "grails.gorm.failOnError"; - private static final String AUTO_FLUSH_CONFIG_PROPERTY = "grails.gorm.autoFlush"; - - /** - * When a domain instance is saved without validation, we put it - * into this thread local variable. Any code that needs to know - * whether the domain instance should be validated can just check - * the value. Note that this only works because the session is - * flushed when a domain instance is saved without validation. - */ - private static ThreadLocal<Set<Integer>> disableAutoValidationFor = new ThreadLocal<Set<Integer>>(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - disableAutoValidationFor.remove(); - } - }); - } - - private static Set<Integer> getDisableAutoValidationFor() { - Set<Integer> identifiers = disableAutoValidationFor.get(); - if (identifiers == null) - disableAutoValidationFor.set(identifiers = new HashSet<Integer>()); - return identifiers; - } - - public static boolean isAutoValidationDisabled(Object obj) { - Set<Integer> identifiers = getDisableAutoValidationFor(); - return obj != null && identifiers.contains(System.identityHashCode(obj)); - } - - public static void clearDisabledValidations(Object obj) { - getDisableAutoValidationFor().remove(System.identityHashCode(obj)); - } - - public static void clearDisabledValidations() { - getDisableAutoValidationFor().clear(); - } - - public AbstractSavePersistentMethod(Pattern pattern, SessionFactory sessionFactory, - ClassLoader classLoader, GrailsApplication application, - GrailsDomainClass domainClass, HibernateDatastore datastore) { - super(pattern, sessionFactory, classLoader, application, datastore.getDefaultFlushMode()); - - this.datastore = datastore; - } - - public AbstractSavePersistentMethod(Pattern pattern, SessionFactory sessionFactory, - ClassLoader classLoader, GrailsApplication application, HibernateDatastore datastore) { - this(pattern, sessionFactory, classLoader, application, null, datastore); - } - - @SuppressWarnings("rawtypes") - private boolean shouldFail(GrailsApplication grailsApplication, GrailsDomainClass domainClass) { - boolean shouldFail = false; - final Map config = grailsApplication.getFlatConfig(); - if (config.containsKey(FAIL_ON_ERROR_CONFIG_PROPERTY)) { - Object configProperty = config.get(FAIL_ON_ERROR_CONFIG_PROPERTY); - if (configProperty instanceof Boolean) { - shouldFail = Boolean.TRUE == configProperty; - } - else if (configProperty instanceof List) { - if (domainClass != null) { - final Class theClass = domainClass.getClazz(); - List packageList = (List) configProperty; - shouldFail = GrailsClassUtils.isClassBelowPackage(theClass, packageList); - } - } - } - return shouldFail; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod#doInvokeInternal(java.lang.Object, java.lang.Object[]) - */ - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(final Object target, Object[] arguments) { - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - target.getClass().getName()); - - DeferredBindingActions.runActions(); - boolean shouldFlush = shouldFlush(arguments); - boolean shouldValidate = shouldValidate(arguments, domainClass); - if (shouldValidate) { - Validator validator = domainClass.getValidator(); - - if (domainClass instanceof DefaultGrailsDomainClass) { - GrailsHibernateUtil.autoAssociateBidirectionalOneToOnes((DefaultGrailsDomainClass) domainClass, target); - } - Errors errors = setupErrorsProperty(target); - - if (validator != null) { - application.getMainContext().publishEvent(new ValidationEvent(datastore, target)); - - boolean deepValidate = true; - Map argsMap = null; - if (arguments.length > 0 && arguments[0] instanceof Map) { - argsMap = (Map) arguments[0]; - } - if (argsMap != null && argsMap.containsKey(ARGUMENT_DEEP_VALIDATE)) { - deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap); - } - - AbstractPersistentConstraint.sessionFactory.set(datastore.getSessionFactory()); - try { - if (deepValidate && (validator instanceof CascadingValidator)) { - ((CascadingValidator)validator).validate(target, errors, deepValidate); - } - else { - validator.validate(target,errors); - } - } - finally { - AbstractPersistentConstraint.sessionFactory.remove(); - } - - if (errors.hasErrors()) { - handleValidationError(domainClass,target,errors); - boolean shouldFail = shouldFail(application, domainClass); - if (argsMap != null && argsMap.containsKey(ARGUMENT_FAIL_ON_ERROR)) { - shouldFail = GrailsClassUtils.getBooleanFromMap(ARGUMENT_FAIL_ON_ERROR, argsMap); - } - if (shouldFail) { - throw new ValidationException("Validation Error(s) occurred during save()", errors); - } - return null; - } - - setObjectToReadWrite(target); - } - } - - // this piece of code will retrieve a persistent instant - // of a domain class property is only the id is set thus - // relieving this burden off the developer - if (domainClass != null) { - autoRetrieveAssocations(domainClass, target); - } - - if (!shouldValidate) { - Set<Integer> identifiers = getDisableAutoValidationFor(); - identifiers.add(System.identityHashCode(target)); - } - - if (shouldInsert(arguments)) { - return performInsert(target, shouldFlush); - } - - return performSave(target, shouldFlush); - } - - @SuppressWarnings("rawtypes") - private boolean shouldInsert(Object[] arguments) { - return arguments.length > 0 && arguments[0] instanceof Map && - GrailsClassUtils.getBooleanFromMap(ARGUMENT_INSERT, (Map) arguments[0]); - } - - @SuppressWarnings("rawtypes") - private boolean shouldFlush(Object[] arguments) { - final boolean shouldFlush; - if (arguments.length > 0 && arguments[0] instanceof Boolean) { - shouldFlush = (Boolean)arguments[0]; - } - else if (arguments.length > 0 && arguments[0] instanceof Map && ((Map) arguments[0]).containsKey(ARGUMENT_FLUSH)) { - shouldFlush = GrailsClassUtils.getBooleanFromMap(ARGUMENT_FLUSH, ((Map) arguments[0])); - } - else { - final Map config = application.getFlatConfig(); - shouldFlush = Boolean.TRUE == config.get(AUTO_FLUSH_CONFIG_PROPERTY); - } - return shouldFlush; - } - - /** - * Performs automatic association retrieval - * @param domainClass The domain class to retrieve associations for - * @param target The target object - */ - @SuppressWarnings("unchecked") - private void autoRetrieveAssocations(GrailsDomainClass domainClass, Object target) { - BeanWrapper bean = new BeanWrapperImpl(target); - HibernateTemplate t = getHibernateTemplate(); - GrailsDomainClassProperty[] props = domainClass.getPersistentProperties(); - for (int i = 0; i < props.length; i++) { - GrailsDomainClassProperty prop = props[i]; - if (!prop.isManyToOne() && !prop.isOneToOne()) { - continue; - } - - Object propValue = bean.getPropertyValue(prop.getName()); - if (propValue == null || t.contains(propValue)) { - continue; - } - - GrailsDomainClass otherSide = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - prop.getType().getName()); - if (otherSide == null) { - continue; - } - - BeanWrapper propBean = new BeanWrapperImpl(propValue); - try { - Serializable id = (Serializable)propBean.getPropertyValue(otherSide.getIdentifier().getName()); - if (id != null) { - final Object propVal = t.get(prop.getType(), id); - if (propVal != null) { - bean.setPropertyValue(prop.getName(), propVal); - } - } - } - catch (InvalidPropertyException ipe) { - // property is not accessable - } - } - } - - /** - * Sets the flush mode to manual. which ensures that the database changes are not persisted to the database - * if a validation error occurs. If save() is called again and validation passes the code will check if there - * is a manual flush mode and flush manually if necessary - * - * @param domainClass The domain class - * @param target The target object that failed validation - * @param errors The Errors instance @return This method will return null signaling a validation failure - */ - protected Object handleValidationError(GrailsDomainClass domainClass, final Object target, Errors errors) { - // if a validation error occurs set the object to read-only to prevent a flush - setObjectToReadOnly(target); - if (domainClass instanceof DefaultGrailsDomainClass) { - DefaultGrailsDomainClass dgdc = (DefaultGrailsDomainClass) domainClass; - List<GrailsDomainClassProperty> associations = dgdc.getAssociations(); - for (GrailsDomainClassProperty association : associations) { - if (association.isOneToOne() || association.isManyToOne()) { - BeanWrapper bean = new BeanWrapperImpl(target); - Object propertyValue = bean.getPropertyValue(association.getName()); - if (propertyValue != null) { - setObjectToReadOnly(propertyValue); - } - } - } - } - setErrorsOnInstance(target, errors); - return null; - } - - /** - * Associates the Errors object on the instance - * - * @param target The target instance - * @param errors The Errors object - */ - protected void setErrorsOnInstance(Object target, Errors errors) { - if (target instanceof GroovyObject) { - ((GroovyObject)target).setProperty(ERRORS_PROPERTY,errors); - } - else { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - metaClass.setProperty(target.getClass() ,target, ERRORS_PROPERTY,errors, false, false); - } - } - - /** - * Checks whether validation should be performed - * @return true if the domain class should be validated - * @param arguments The arguments to the validate method - * @param domainClass The domain class - */ - @SuppressWarnings("rawtypes") - private boolean shouldValidate(Object[] arguments, GrailsDomainClass domainClass) { - if (domainClass == null) { - return false; - } - - if (arguments.length == 0) { - return true; - } - - if (arguments[0] instanceof Boolean) { - return (Boolean)arguments[0]; - } - - if (arguments[0] instanceof Map) { - Map argsMap = (Map)arguments[0]; - if (argsMap.containsKey(ARGUMENT_VALIDATE)) { - return GrailsClassUtils.getBooleanFromMap(ARGUMENT_VALIDATE, argsMap); - } - - return true; - } - - return true; - } - - /** - * Subclasses should override and perform a save operation, flushing the session if the second argument is true - * - * @param target The target object to save - * @param shouldFlush Whether to flush - * @return The target object - */ - protected abstract Object performSave(Object target, boolean shouldFlush); - - /** - * Subclasses should override and perform an insert operation, flushing the session if the second argument is true - * - * @param target The target object to save - * @param shouldFlush Whether to flush - * @return The target object - */ - protected abstract Object performInsert(Object target, boolean shouldFlush); -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java deleted file mode 100644 index 58b128c..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java +++ /dev/null
@@ -1,121 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.HibernateCriteriaBuilder; -import groovy.lang.Closure; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.metaclass.AbstractStaticMethodInvocation; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.HibernateSession; -import org.codehaus.groovy.grails.orm.hibernate.query.HibernateQuery; -import org.grails.datastore.gorm.finders.DynamicFinder; -import org.grails.datastore.gorm.finders.FinderMethod; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.util.Assert; - -/** - * Abstract base class for static persistent methods. - * - * @author Steven Devijver - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractStaticPersistentMethod extends AbstractStaticMethodInvocation implements FinderMethod { - - private ClassLoader classLoader; - private GrailsHibernateTemplate hibernateTemplate; - private SessionFactory sessionFactory; - protected final GrailsApplication application; - - protected AbstractStaticPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, Pattern pattern, GrailsApplication application, int defaultFlushMode) { - Assert.notNull(sessionFactory, "Session factory is required!"); - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.application = application; - setPattern(pattern); - this.classLoader = classLoader; - this.sessionFactory = sessionFactory; - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, application, defaultFlushMode); - } - - protected SessionFactory getSessionFactory() { - return sessionFactory; - } - - protected GrailsHibernateTemplate getHibernateTemplate() { - return hibernateTemplate; - } - - @Override - public Object invoke(Class clazz, String methodName, Object[] arguments) { - return invoke(clazz, methodName, (Closure) null, arguments); - } - - public Object invoke(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(clazz, methodName, additionalCriteria, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - public Object invoke(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(clazz, methodName, additionalCriteria, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - protected Criteria getCriteria(HibernateDatastore datastore, GrailsApplication appliation, Session session, DetachedCriteria detachedCriteria, Closure additionalCriteria, Class<?> clazz) { - if (additionalCriteria != null) { - HibernateCriteriaBuilder builder = new HibernateCriteriaBuilder(clazz, session.getSessionFactory()); - builder.setGrailsApplication(appliation); - builder.setConversionService(datastore.getMappingContext().getConversionService()); - builder.setDefaultFlushMode(datastore.getDefaultFlushMode()); - return builder.buildCriteria(additionalCriteria); - } - - Criteria criteria = session.createCriteria(clazz); - if (detachedCriteria != null) { - HibernateSession hibernateSession = new HibernateSession(datastore, session.getSessionFactory()); - PersistentEntity persistentEntity = datastore.getMappingContext().getPersistentEntity(clazz.getName()); - if (persistentEntity != null) { - DynamicFinder.applyDetachedCriteria(new HibernateQuery(criteria, hibernateSession, persistentEntity), detachedCriteria); - } - } - hibernateTemplate.applySettings(criteria); - return criteria; - } - - protected abstract Object doInvokeInternal(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments); - - protected abstract Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments); -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java deleted file mode 100644 index cb54d19..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java +++ /dev/null
@@ -1,93 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Dynamic method that allows counting the values of the specified property names - * - * eg. Account.countByBranch('London') // returns how many accounts are in london - * - * @author Graeme Rocher - */ -public class CountByPersistentMethod extends AbstractClausedStaticPersistentMethod { - - private static final String OPERATOR_OR = "Or"; - private static final String OPERATOR_AND = "And"; - - private static final Pattern METHOD_PATTERN = Pattern.compile("(countBy)(\\w+)"); - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - - public CountByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader) { - super(application, sessionFactory, classLoader, METHOD_PATTERN, OPERATORS, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Long doInvokeInternalWithExpressions(final Class clazz, final String methodName, final Object[] arguments, - final List expressions, final String operatorInUse, final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - - return getHibernateTemplate().execute(new HibernateCallback<Long>() { - public Long doInHibernate(Session session) throws HibernateException, SQLException { - final Criteria crit = getCriteria(datastore, application, session, detachedCriteria, additionalCriteria, clazz); - crit.setProjection(Projections.rowCount()); - String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - Map argsMap = (arguments.length > 1 && (arguments[1] instanceof Map)) ? (Map) arguments[1] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argsMap, conversionService, false); - - populateCriteriaWithExpressions(crit, operator, expressions); - return (Long) crit.uniqueResult(); - } - }); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected void populateCriteriaWithExpressions(Criteria crit, String operator, List expressions) { - if (operator.equals(OPERATOR_OR)) { - Disjunction dis = Restrictions.disjunction(); - for (GrailsMethodExpression current : (List<GrailsMethodExpression>)expressions) { - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (GrailsMethodExpression current : (List<GrailsMethodExpression>)expressions) { - crit.add(current.getCriterion()); - } - } - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java deleted file mode 100644 index d529918..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java +++ /dev/null
@@ -1,205 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Allows the executing of arbitrary HQL queries. - * <p/> - * eg. Account.executeQuery("select distinct a.number from Account a where a.branch = ?", 'London') or - * Account.executeQuery("select distinct a.number from Account a where a.branch = :branch", [branch:'London']) - * - * @author Graeme Rocher - * @author Sergey Nebolsin - * @see <a href="http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html">http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html</a> - * @since 30-Apr-2006 - */ -public class ExecuteQueryPersistentMethod extends AbstractStaticPersistentMethod { - private static final String METHOD_SIGNATURE = "executeQuery"; - private static final Pattern METHOD_PATTERN = Pattern.compile("^executeQuery$"); - - private static final List<String> QUERY_META_PARAMS = Arrays.asList( - GrailsHibernateUtil.ARGUMENT_MAX, - GrailsHibernateUtil.ARGUMENT_OFFSET, - GrailsHibernateUtil.ARGUMENT_CACHE, - GrailsHibernateUtil.ARGUMENT_FLUSH_MODE, - GrailsHibernateUtil.ARGUMENT_TIMEOUT, - GrailsHibernateUtil.ARGUMENT_FETCH_SIZE, - GrailsHibernateUtil.ARGUMENT_READ_ONLY); - - private final ConversionService conversionService; - - public ExecuteQueryPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, METHOD_PATTERN, application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { - checkMethodSignature(clazz, arguments); - - final String query = arguments[0].toString(); - final Map queryMetaParams = extractQueryMetaParams(arguments); - final List positionalParams = extractPositionalParams(arguments); - final Map namedParams = extractNamedParams(arguments); - - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - // process paginate params - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_MAX)) { - Integer maxParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_MAX), Integer.class); - q.setMaxResults(maxParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_OFFSET)) { - Integer offsetParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_OFFSET), Integer.class); - q.setFirstResult(offsetParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_CACHE)) { - q.setCacheable((Boolean)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_CACHE)); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_FETCH_SIZE)) { - Integer fetchSizeParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_FETCH_SIZE), Integer.class); - q.setFetchSize(fetchSizeParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_TIMEOUT)) { - Integer timeoutParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_TIMEOUT), Integer.class); - q.setTimeout(timeoutParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_READ_ONLY)) { - q.setReadOnly((Boolean)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_READ_ONLY)); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_FLUSH_MODE)) { - q.setFlushMode((FlushMode)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_FLUSH_MODE)); - } - // process positional HQL params - int index = 0; - for (Object parameter : positionalParams) { - q.setParameter(index++, parameter instanceof CharSequence ? parameter.toString() : parameter); - } - - // process named HQL params - for (Object o : namedParams.entrySet()) { - Map.Entry entry = (Map.Entry) o; - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be of type String"); - } - String parameterName = (String) entry.getKey(); - if (!QUERY_META_PARAMS.contains(parameterName)) { - Object parameterValue = entry.getValue(); - if (parameterValue == null) { - throw new IllegalArgumentException("Named parameter [" + entry.getKey() + "] value may not be null"); - } - if (Collection.class.isAssignableFrom(parameterValue.getClass())) { - q.setParameterList(parameterName, (Collection) parameterValue); - } - else if (parameterValue.getClass().isArray()) { - q.setParameterList(parameterName, (Object[]) parameterValue); - } - else if (parameterValue instanceof CharSequence) { - q.setParameter(parameterName, parameterValue.toString()); - } - else { - q.setParameter(parameterName, parameterValue); - } - } - } - return q.list(); - } - }); - } - - @SuppressWarnings("rawtypes") - private void checkMethodSignature(Class clazz, Object[] arguments) { - boolean valid = true; - if (arguments.length < 1) valid = false; - else if (arguments.length == 3 && !(arguments[2] instanceof Map)) valid = false; - else if (arguments.length > 3) valid = false; - - if (!valid) throw new MissingMethodException(METHOD_SIGNATURE, clazz, arguments); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Map extractQueryMetaParams(Object[] arguments) { - Map result = new HashMap(); - int metaParamsIndex = 0; - if (arguments.length == 2 && arguments[1] instanceof Map) metaParamsIndex = 1; - else if (arguments.length == 3) metaParamsIndex = 2; - if (metaParamsIndex > 0) { - Map sourceMap = (Map) arguments[metaParamsIndex]; - for (String queryMetaParam : QUERY_META_PARAMS) { - if (sourceMap.containsKey(queryMetaParam)) { - result.put(queryMetaParam, sourceMap.get(queryMetaParam)); - } - } - } - return result; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private List extractPositionalParams(Object[] arguments) { - List result = new ArrayList(); - if (arguments.length < 2 || arguments[1] instanceof Map) return result; - if (arguments[1] instanceof Collection) { - result.addAll((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - result.addAll(Arrays.asList((Object[]) arguments[1])); - } - else { - result.add(arguments[1]); - } - return result; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Map extractNamedParams(Object[] arguments) { - Map result = new HashMap(); - if (arguments.length < 2 || !(arguments[1] instanceof Map)) return result; - result.putAll((Map) arguments[1]); - return result; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java deleted file mode 100644 index 5126bf9..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java +++ /dev/null
@@ -1,146 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateCallback; -import org.springframework.orm.hibernate3.SessionFactoryUtils; - -/** - * Allows the executing of arbitrary HQL updates. - * <p/> - * eg. Account.executeUpdate("delete from Account a where a.branch = ?", 'London') or - * Account.executeUpdate("delete from Account a where a.branch = :branch", [branch:'London']) - * - * @author Burt Beckwith - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public class ExecuteUpdatePersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_SIGNATURE = "executeUpdate"; - private static final Pattern METHOD_PATTERN = Pattern.compile("^executeUpdate$"); - - public ExecuteUpdatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, int defaultFlushMode) { - super(sessionFactory, classLoader, METHOD_PATTERN, application, defaultFlushMode); - } - - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @Override - protected Object doInvokeInternal(final Class clazz, final String methodName, Closure additionalCriteria, final Object[] arguments) { - - checkMethodSignature(clazz, arguments); - - return getHibernateTemplate().execute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(arguments[0].toString()); - getHibernateTemplate().applySettings(q); - SessionFactoryUtils.applyTransactionTimeout(q, getHibernateTemplate().getSessionFactory()); - - // process positional HQL params - int index = 0; - for (Object parameter : extractPositionalParams(arguments)) { - q.setParameter(index++, parameter); - } - - // process named HQL params - for (Map.Entry entry : (Set<Map.Entry>)extractNamedParams(arguments).entrySet()) { - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be of type String"); - } - - String parameterName = (String)entry.getKey(); - Object parameterValue = entry.getValue(); - if (Collection.class.isAssignableFrom(parameterValue.getClass())) { - q.setParameterList(parameterName, (Collection)parameterValue); - } - else if (parameterValue.getClass().isArray()) { - q.setParameterList(parameterName, (Object[])parameterValue); - } - else if (parameterValue instanceof CharSequence) { - q.setParameter(parameterName, parameterValue.toString()); - } - else { - q.setParameter(parameterName, parameterValue); - } - } - return q.executeUpdate(); - } - }); - } - - private void checkMethodSignature(Class clazz, Object[] arguments) { - boolean valid = true; - if (arguments.length == 0 || arguments.length > 2) { - valid = false; - } - else if (arguments.length == 2 && !(arguments[1] instanceof Map || arguments[1] instanceof Collection)) { - valid = false; - } - - if (!valid) { - throw new MissingMethodException(METHOD_SIGNATURE, clazz, arguments); - } - } - - private List extractPositionalParams(Object[] arguments) { - if (arguments.length == 1 || arguments[1] instanceof Map) { - return Collections.EMPTY_LIST; - } - - List result = new ArrayList(); - if (arguments[1] instanceof Collection) { - result.addAll((Collection)arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - result.addAll(Arrays.asList((Object[])arguments[1])); - } - else { - result.add(arguments[1]); - } - - return result; - } - - private Map extractNamedParams(Object[] arguments) { - if (arguments.length == 1 || !(arguments[1] instanceof Map)) { - return Collections.EMPTY_MAP; - } - - return (Map)arguments[1]; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java deleted file mode 100644 index 985fe1e..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java +++ /dev/null
@@ -1,49 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "findAll<booleanProperty>By*" static persistent method. This method allows querying for - * instances of grails domain classes based on a boolean property and any other arbitrary - * properties. - * - * eg. - * Account.findAllActiveByHolder("Joe Blogs"); // Where class "Account" has a properties called "active" and "holder" - * Account.findAllActiveByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "active', "holder" and "branch" - * - * In both of those queries, the query will only select Account objects where active=true. - * - * @author Jeff Brown - */ -public class FindAllByBooleanPropertyPersistentMethod extends FindAllByPersistentMethod { - - private static final String METHOD_PATTERN = "(findAll)((\\w+)(By)([A-Z]\\w*)|(\\w+))"; - - public FindAllByBooleanPropertyPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader); - setPattern(Pattern.compile(METHOD_PATTERN)); - } - - @Override - protected boolean firstExpressionIsRequiredBoolean() { - return true; - } -} \ No newline at end of file
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java deleted file mode 100644 index 9b18a7a..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java +++ /dev/null
@@ -1,128 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Restrictions; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * The "findBy*" static persistent method. This method allows querying for - * instances of grails domain classes based on their properties. This method returns a list of all found results - * - * eg. - * Account.findAllByHolder("Joe Blogs"); // Where class "Account" has a property called "holder" - * Account.findAllByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "holder" and "branch" - * - * @author Graeme Rocher - */ -public class FindAllByPersistentMethod extends AbstractClausedStaticPersistentMethod { - - private static final String OPERATOR_OR = "Or"; - private static final String OPERATOR_AND = "And"; - private static final String METHOD_PATTERN = "(findAllBy)([A-Z]\\w*)"; - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindAllByPersistentMethod(HibernateDatastore datastore,GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader) { - super(application, sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), OPERATORS, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternalWithExpressions(final Class clazz, String methodName, - final Object[] arguments, final List expressions, String operatorInUse, - final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - - final String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - final Criteria c = getCriteria(datastore,application, session,detachedCriteria, additionalCriteria, clazz); - - Map argsMap = (arguments.length > 0 && (arguments[0] instanceof Map)) ? (Map) arguments[0] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argsMap, conversionService); - - if (operator.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - GrailsMethodExpression expression = (GrailsMethodExpression) expressions.remove(0); - c.add(expression.getCriterion()); - } - - Disjunction dis = Restrictions.disjunction(); - int numberOfForceNoResultsCriterion = 0; - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - if (GrailsMethodExpression.FORCE_NO_RESULTS == current.getCriterion()) { - numberOfForceNoResultsCriterion++; - } else { - dis.add(current.getCriterion()); - } - } - if (numberOfForceNoResultsCriterion > 0 && numberOfForceNoResultsCriterion == expressions.size()) { - return Collections.EMPTY_LIST; - } - c.add(dis); - } - else { - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - if (GrailsMethodExpression.FORCE_NO_RESULTS == current.getCriterion()) { - return Collections.emptyList(); - } - c.add(current.getCriterion()); - } - } - - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - }); - } - - /** - * Indicates if the first expression in the query is a required boolean property and as such should - * be ANDed to the other expressions, not ORed. - * - * @return true if the first expression is a required boolean property, false otherwise - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByBooleanPropertyPersistentMethod - */ - protected boolean firstExpressionIsRequiredBoolean() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java deleted file mode 100644 index 8604572..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java +++ /dev/null
@@ -1,294 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.util.GrailsNameUtils; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Example; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * <p> - * The "findAll" persistent static method allows searching for instances using - * either an example instance or an HQL query. Max results and offset parameters could - * be specified. A GrailsQueryException is thrown if the query is not a valid query - * for the domain class. - * <p> - * Syntax: - * DomainClass.findAll(query, params?) - * DomainClass.findAll(query, params?, max) - * DomainClass.findAll(query, params?, max, offset) - * DomainClass.findAll(query, params?, [max:10, offset:5]) - * - * <p> - * Examples in Groovy: <code> - * // retrieves all accounts - * def a = Account.findAll() - * - * // retrieve all accounts ordered by account number - * def a = Account.findAll("from Account as a order by a.number asc") - * - * // retrieve first 10 accounts ordered by account number - * def a = Account.findAll("from Account as a order by a.number asc",10) - * - * // retrieve first 10 accounts ordered by account number started from 5th account - * def a = Account.findAll("from Account as a order by a.number asc",10,5) - * - * // retrieve first 10 accounts ordered by account number started from 5th account - * def a = Account.findAll("from Account as a order by a.number asc",[max:10,offset:5]) - * - * // with query parameters - * def a = Account.find("from Account as a where a.number = ? and a.branch = ?", [38479, "London"]) - * - * // with query named parameters - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"]) - * - * // with query named parameters and max results and offset - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"], 10, 5) - * - * // with query named parameters and max results and offset map - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"], [max:10, offset:5]) - * - * // query by example - * def a = new Account() - * a.number = 495749357 - * def a = Account.find(a) - * - * </code> - * - * @author Graeme Rocher - * @author Steven Devijver - * @author Sergey Nebolsin - * - * @since 0.1 - */ -public class FindAllPersistentMethod extends AbstractStaticPersistentMethod { - private final ConversionService conversionService; - - public FindAllPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile("^findAll$"), application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - if (arguments.length == 0) { - return getHibernateTemplate().loadAll(clazz); - } - - final Object arg = arguments[0] instanceof CharSequence ? arguments[0].toString() : arguments[0]; - - // if the arg is an instance of the class find by example - if (arg instanceof String) { - final String query = ((String) arg).trim(); - final String shortName = GrailsNameUtils.getShortName(clazz); - if (!query.matches("(?i)from(?-i)\\s+[" + clazz.getName() + "|" + shortName + "].*")) { - throw new GrailsQueryException("Invalid query [" + query + "] for domain class [" + clazz + "]"); - } - - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - - Object[] queryArgs = null; - Map queryNamedArgs = null; - int max = retrieveMaxValue(); - int offset = retrieveOffsetValue(); - boolean useCache = useCache(); - if (arguments.length > 1) { - if (arguments[1] instanceof Collection) { - queryArgs = GrailsClassUtils.collectionToObjectArray((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - queryArgs = (Object[]) arguments[1]; - } - else if (arguments[1] instanceof Map) { - queryNamedArgs = (Map) arguments[1]; - } - } - - if (queryArgs != null) { - for (int i = 0; i < queryArgs.length; i++) { - if (queryArgs[i] instanceof CharSequence) { - q.setParameter(i, queryArgs[i].toString()); - } else { - q.setParameter(i, queryArgs[i]); - } - } - } - if (queryNamedArgs != null) { - for (Object o : queryNamedArgs.entrySet()) { - Map.Entry entry = (Map.Entry) o; - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be String: " + queryNamedArgs); - } - String stringKey = (String) entry.getKey(); - // Won't try to bind these parameters since they are processed separately - if (GrailsHibernateUtil.ARGUMENT_MAX.equals(stringKey) || GrailsHibernateUtil.ARGUMENT_OFFSET.equals(stringKey) || GrailsHibernateUtil.ARGUMENT_CACHE.equals(stringKey)) - continue; - Object value = entry.getValue(); - if (value == null) { - q.setParameter(stringKey, null); - } else if (value instanceof CharSequence) { - q.setParameter(stringKey, value.toString()); - } else if (List.class.isAssignableFrom(value.getClass())) { - q.setParameterList(stringKey, (List) value); - } else if (value.getClass().isArray()) { - q.setParameterList(stringKey, (Object[]) value); - } else { - q.setParameter(stringKey, value); - } - } - } - if (max > 0) { - q.setMaxResults(max); - } - if (offset > 0) { - q.setFirstResult(offset); - } - q.setCacheable(useCache); - return q.list(); - } - - private boolean useCache() { - boolean useCache = getHibernateTemplate().isCacheQueries(); - if (arguments.length > 1 && arguments[arguments.length - 1] instanceof Map) { - useCache = retrieveBoolean(arguments[arguments.length - 1], GrailsHibernateUtil.ARGUMENT_CACHE); - } - return useCache; - } - - private int retrieveMaxValue() { - int result = -1; - if (arguments.length > 1) { - result = retrieveInt(arguments[1], GrailsHibernateUtil.ARGUMENT_MAX); - if (arguments.length > 2 && result == -1) { - result = retrieveInt(arguments[2], GrailsHibernateUtil.ARGUMENT_MAX); - } - } - return result; - } - - private int retrieveOffsetValue() { - int result = -1; - if (arguments.length > 1) { - if (isMapWithValue(arguments[1], GrailsHibernateUtil.ARGUMENT_OFFSET)) { - result = ((Number)((Map)arguments[1]).get(GrailsHibernateUtil.ARGUMENT_OFFSET)).intValue(); - } - if (arguments.length > 2 && result == -1) { - if (isMapWithValue(arguments[2], GrailsHibernateUtil.ARGUMENT_OFFSET)) { - result = retrieveInt(arguments[2], GrailsHibernateUtil.ARGUMENT_OFFSET); - } - else if (isIntegerOrLong(arguments[1]) && isIntegerOrLong(arguments[2])) { - result = ((Number)arguments[2]).intValue(); - } - } - if (arguments.length > 3 && result == -1) { - if (isIntegerOrLong(arguments[3])) { - result = ((Number)arguments[3]).intValue(); - } - } - } - return result; - } - - private boolean retrieveBoolean(Object param, String key) { - boolean value = false; - if (isMapWithValue(param, key)) { - value = conversionService.convert(((Map)param).get(key), Boolean.class); - } - return value; - } - - private int retrieveInt(Object param, String key) { - if (isMapWithValue(param, key)) { - return conversionService.convert(((Map) param).get(key),Integer.class); - } - if (isIntegerOrLong(param)) { - return ((Number)param).intValue(); - } - return -1; - } - - private boolean isIntegerOrLong(Object param) { - return (param instanceof Integer) || (param instanceof Long); - } - - private boolean isMapWithValue(Object param, String key) { - return (param instanceof Map) && ((Map)param).containsKey(key); - } - }); - } - - if (clazz.isAssignableFrom(arg.getClass())) { - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - Example example = Example.create(arg).ignoreCase(); - - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - crit.add(example); - - Map argsMap = (arguments.length > 1 && (arguments[1] instanceof Map)) ? (Map) arguments[1] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application,clazz, crit, argsMap, conversionService); - return crit.list(); - } - }); - } - - if (arguments[0] instanceof Map) { - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, (Map)arguments[0], conversionService); - return crit.list(); - } - }); - } - - throw new MissingMethodException(methodName, clazz, arguments); - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java deleted file mode 100644 index ed086a5..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java +++ /dev/null
@@ -1,49 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "find<booleanProperty>By*" static persistent method. This method allows querying for - * instances of grails domain classes based on a boolean property and any other arbitrary - * properties. This method returns the first result of the query. - * - * eg. - * Account.findActiveByHolder("Joe Blogs"); // Where class "Account" has a properties called "active" and "holder" - * Account.findActiveByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "active', "holder" and "branch" - * - * In both of those queries, the query will only select Account objects where active=true. - * - * @author Jeff Brown - */ -public class FindByBooleanPropertyPersistentMethod extends FindByPersistentMethod { - - private static final String METHOD_PATTERN = "(find)((\\w+)(By)([A-Z]\\w*)|(\\w++))"; - - public FindByBooleanPropertyPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader); - setPattern(Pattern.compile(METHOD_PATTERN)); - } - - @Override - protected boolean firstExpressionIsRequiredBoolean() { - return true; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java deleted file mode 100644 index 973df99..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java +++ /dev/null
@@ -1,47 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "findBy*" static persistent method. This method allows querying for - * instances of grails domain classes based on their properties. This method returns the first result of the query - * - * eg. - * Account.findByHolder("Joe Blogs"); // Where class "Account" has a property called "holder" - * Account.findByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "holder" and "branch" - * - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public class FindByPersistentMethod extends AbstractFindByPersistentMethod { - - private static final String METHOD_PATTERN = "(findBy)([A-Z]\\w*)"; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore,application,sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), OPERATORS); - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java deleted file mode 100644 index 306f352..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java +++ /dev/null
@@ -1,89 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MissingMethodException; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -@SuppressWarnings("rawtypes") -public class FindOrCreateByPersistentMethod extends AbstractFindByPersistentMethod { - - private static final String METHOD_PATTERN = "(findOrCreateBy)([A-Z]\\w*)"; - - public FindOrCreateByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - this(datastore, application,sessionFactory, classLoader, METHOD_PATTERN); - } - - public FindOrCreateByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader, String pattern) { - super(datastore, application,sessionFactory, classLoader, Pattern.compile(pattern), OPERATORS); - } - - @SuppressWarnings("unchecked") - @Override - protected Object doInvokeInternalWithExpressions(Class clazz, - String methodName, Object[] arguments, List expressions, - String operatorInUse, DetachedCriteria detachedCriteria, Closure additionalCriteria) { - boolean isValidMethod = true; - - if (OPERATOR_OR.equals(operatorInUse)) { - isValidMethod = false; - } - - Iterator iterator = expressions.iterator(); - while (isValidMethod && iterator.hasNext()) { - GrailsMethodExpression gme = (GrailsMethodExpression) iterator.next(); - isValidMethod = GrailsMethodExpression.EQUAL.equals(gme.type); - } - - if (!isValidMethod) { - throw new MissingMethodException(methodName, clazz, arguments); - } - Object result = super.doInvokeInternalWithExpressions(clazz, methodName, arguments, - expressions, operatorInUse, detachedCriteria, additionalCriteria); - - if (result == null) { - Map m = new HashMap(); - for (Object o : expressions) { - GrailsMethodExpression gme = (GrailsMethodExpression) o; - m.put(gme.getPropertyName(), gme.getArguments()[0]); - } - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(clazz); - result = metaClass.invokeConstructor(new Object[]{m}); - if (shouldSaveOnCreate()) { - metaClass.invokeMethod(result, "save", null); - } - } - - return result; - } - - protected boolean shouldSaveOnCreate() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java deleted file mode 100644 index bae7713..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java +++ /dev/null
@@ -1,40 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -public class FindOrSaveByPersistentMethod extends FindOrCreateByPersistentMethod { - - private static final String METHOD_PATTERN = "(findOrSaveBy)([A-Z]\\w*)"; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindOrSaveByPersistentMethod(HibernateDatastore datastore,GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader, METHOD_PATTERN); - } - - @Override - protected boolean shouldSaveOnCreate() { - return true; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java deleted file mode 100644 index 2028e74..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java +++ /dev/null
@@ -1,207 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.util.GrailsNameUtils; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Example; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * <p> - * The "find" persistent static method allows searching for instances using - * either an example instance or an HQL query. This method returns the first - * result of the query. A GrailsQueryException is thrown if the query is not a - * valid query for the domain class. - * - * <p> - * Examples in Groovy: <code> - * // retrieve the first account ordered by account number - * def a = Account.find("from Account as a order by a.number asc") - * - * // with query parameters - * def a = Account.find("from Account as a where a.number = ? and a.branch = ?", [38479, "London"]) - * - * // with query named parameters - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"]) - - * // query by example - * def a = new Account() - * a.number = 495749357 - * def a = Account.find(a) - * - * </code> - * - * @author Graeme Rocher - * @author Sergey Nebolsin - */ -public class FindPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "^find$"; - private final ConversionService conversionService; - - public FindPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - - if (arguments.length == 0) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - final Object arg = arguments[0] instanceof CharSequence ? arguments[0].toString() : arguments[0]; - - if (arg instanceof String) { - final String query = (String) arg; - final String shortName = GrailsNameUtils.getShortName(clazz); - if (!query.matches("(?i)from(?-i)\\s+[" + clazz.getName() + "|" + shortName + "].*")) { - throw new GrailsQueryException("Invalid query [" + query + "] for domain class [" + clazz + "]"); - } - - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - Object[] queryArgs = null; - Map queryNamedArgs = null; - boolean useCache = useCache(arguments); - - if (arguments.length > 1) { - if (arguments[1] instanceof Collection) { - queryArgs = GrailsClassUtils.collectionToObjectArray((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - queryArgs = (Object[]) arguments[1]; - } - else if (arguments[1] instanceof Map) { - queryNamedArgs = (Map) arguments[1]; - } - } - if (queryArgs != null) { - for (int i = 0; i < queryArgs.length; i++) { - if (queryArgs[i] instanceof CharSequence) { - q.setParameter(i, queryArgs[i].toString()); - } - else { - q.setParameter(i, queryArgs[i]); - } - } - } - if (queryNamedArgs != null) { - for (Iterator it = queryNamedArgs.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be String: " + - queryNamedArgs.toString()); - } - String stringKey = (String) entry.getKey(); - Object value = entry.getValue(); - - if (GrailsHibernateUtil.ARGUMENT_CACHE.equals(stringKey)) { - continue; - } - else if (value instanceof CharSequence) { - q.setParameter(stringKey, value.toString()); - } - else if (List.class.isAssignableFrom(value.getClass())) { - q.setParameterList(stringKey, (List) value); - } - else if (value.getClass().isArray()) { - q.setParameterList(stringKey, (Object[]) value); - } - else { - q.setParameter(stringKey, value); - } - } - } - // only want one result, could have used uniqueObject here - // but it throws an exception if its not unique which is undesirable - q.setMaxResults(1); - q.setCacheable(useCache); - List results = q.list(); - if (results.size() > 0) { - return GrailsHibernateUtil.unwrapIfProxy(results.get(0)); - } - return null; - } - - private boolean useCache(Object[] args) { - boolean useCache = getHibernateTemplate().isCacheQueries(); - if (args.length > 1 && args[args.length - 1] instanceof Map) { - Object param = args[args.length - 1]; - String key = GrailsHibernateUtil.ARGUMENT_CACHE; - boolean value = false; - if ((param instanceof Map) && ((Map)param).containsKey(key)) { - value = conversionService.convert(((Map)param).get(key), Boolean.class); - } - useCache = value; - } - return useCache; - } - }); - } - else if (clazz.isAssignableFrom(arg.getClass())) { - // if the arg is an instance of the class find by example - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - Example example = Example.create(arg).ignoreCase(); - - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - crit.add(example); - crit.setMaxResults(1); - List results = crit.list(); - if (results.size() > 0) { - return results.get(0); - } - return null; - } - }); - } - - throw new MissingMethodException(methodName, clazz, arguments); - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java deleted file mode 100644 index 731d588..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java +++ /dev/null
@@ -1,96 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Order; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * The "listOrderBy*" static persistent method. Allows ordered listing of instances based on their properties. - * - * eg. - * Account.listOrderByHolder(); - * Account.listOrderByHolder(max); // max results - * - * @author Graeme - */ -public class ListOrderByPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "(listOrderBy)(\\w+)"; - private final HibernateDatastore datastore; - - public ListOrderByPersistentMethod(HibernateDatastore datastore, GrailsApplication grailsApplication, SessionFactory sessionFactory, ClassLoader classLoader) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication, datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod#doInvokeInternal(java.lang.Class, java.lang.String, java.lang.Object[]) - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, final Closure additionalCriteria, final Object[] arguments) { - - Matcher match = getPattern().matcher(methodName); - match.find(); - - String nameInSignature = match.group(2); - final String propertyName = nameInSignature.substring(0,1).toLowerCase(Locale.ENGLISH) + nameInSignature.substring(1); - - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = getCriteria(datastore, application, session, null, additionalCriteria, clazz); - - if (arguments != null && arguments.length > 0) { - if (arguments[0] instanceof Map) { - Map argMap = (Map)arguments[0]; - argMap.put(GrailsHibernateUtil.ARGUMENT_SORT,propertyName); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argMap, datastore.getMappingContext().getConversionService()); - } - else { - crit.addOrder(Order.asc(propertyName)); - } - } - else { - crit.addOrder(Order.asc(propertyName)); - } - crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return crit.list(); - } - }); - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java deleted file mode 100644 index 3871c6c..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java +++ /dev/null
@@ -1,89 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.PagedResultList; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * The "list" persistent static method. This method lists of of the persistent - * instances up the maximum specified amount (if any) - * - * eg. - * Account.list(); // list all - * Account.list(max:10,offset:50,sort:"holder",order:"desc"); // list up to 10, offset by 50, sorted by holder and in descending order - * - * @author Graeme Rocher - */ -public class ListPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "^list$"; - private final ConversionService conversionService; - - public ListPersistentMethod(GrailsApplication grailsApplication, SessionFactory sessionFactory, ClassLoader classLoader, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication, defaultFlushMode); - this.conversionService = conversionService; - } - - @Override - @SuppressWarnings("rawtypes") - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - // and list up to the max - return getHibernateTemplate().executeFind(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria c = session.createCriteria(clazz); - getHibernateTemplate().applySettings(c); - if (arguments.length > 0 && arguments[0] instanceof Map) { - Map argMap = (Map)arguments[0]; - if (argMap.containsKey(GrailsHibernateUtil.ARGUMENT_MAX)) { - c.setMaxResults(Integer.MAX_VALUE); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argMap, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return new PagedResultList(getHibernateTemplate(), c); - } - - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argMap, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, Collections.EMPTY_MAP, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - }); - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java deleted file mode 100644 index 4c2cc8a..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java +++ /dev/null
@@ -1,74 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.sql.SQLException; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * The merge() method follows the semantics of merge which attempts to "merge" an object - * with a long lived session. - * - * @author Graeme Rocher - * @since 0.3 - */ -public class MergePersistentMethod extends AbstractSavePersistentMethod { - - public static final String METHOD_SIGNATURE = "merge"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - - public MergePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore); - } - - public MergePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, GrailsDomainClass dc, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, dc, datastore); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod#performSave(java.lang.Object) - */ - @Override - protected Object performSave(final Object target, final boolean flush) { - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Object merged = session.merge(target); - session.lock(merged, LockMode.NONE); - - if (flush) { - session.flush(); - } - return merged; - } - }); - } - - @Override - protected Object performInsert(Object target, boolean shouldFlush) { - throw new IllegalArgumentException("The [insert] argument is not supported by the [merge] method"); - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java deleted file mode 100644 index 3329d96..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java +++ /dev/null
@@ -1,94 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.sql.SQLException; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Follows the semantics of saveOrUpdate of scheduling the object for persistence when a flush occurs. - * - * @author Steven Devijver - * @author Graeme Rocher - * - * @since 0.1 - */ -public class SavePersistentMethod extends AbstractSavePersistentMethod { - - public static final String METHOD_SIGNATURE = "save"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - - public SavePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore); - } - - public SavePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, GrailsDomainClass domainClass, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, domainClass, datastore); - } - - @Override - protected Object performSave(final Object target, final boolean flush) { - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - session.saveOrUpdate(target); - if (flush) { - flushSession(session); - } - return target; - } - }); - } - - @Override - protected Object performInsert(final Object target, final boolean shouldFlush) { - return getHibernateTemplate().execute(new HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - try { - ClosureEventTriggeringInterceptor.markInsertActive(); - session.save(target); - if (shouldFlush) { - flushSession(session); - } - return target; - } finally { - ClosureEventTriggeringInterceptor.resetInsertActive(); - } - } - }); - } - - protected void flushSession(Session session) throws HibernateException { - try { - session.flush(); - } catch (HibernateException e) { - // session should not be flushed again after a data acccess exception! - session.setFlushMode(FlushMode.MANUAL); - throw e; - } - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java deleted file mode 100644 index cc2d490..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java +++ /dev/null
@@ -1,177 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.ValidationErrors; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint; -import org.codehaus.groovy.grails.validation.CascadingValidator; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.SessionFactory; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; -import org.springframework.validation.FieldError; -import org.springframework.validation.ObjectError; -import org.springframework.validation.Validator; - -/** - * Validates an instance of a domain class against its constraints. - * - * @author Graeme Rocher - * @since 07-Nov-2005 - */ -public class ValidatePersistentMethod extends AbstractDynamicPersistentMethod { - - public static final String METHOD_SIGNATURE = "validate"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - public static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; - private static final String ARGUMENT_EVICT = "evict"; - private Validator validator; - private HibernateDatastore datastore; - - public ValidatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application) { - this(sessionFactory, classLoader, application, null, null); - } - - public ValidatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, Validator validator, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore.getDefaultFlushMode()); - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.validator = validator; - this.datastore = datastore; - } - - @Override - @SuppressWarnings({"unchecked","rawtypes"}) - protected Object doInvokeInternal(final Object target, Object[] arguments) { - Errors errors = setupErrorsProperty(target); - - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - target.getClass().getName()); - - if (validator == null && domainClass != null) { - validator = domainClass.getValidator(); - } - - if (validator == null) { - return true; - } - - Boolean valid = Boolean.TRUE; - // should evict? - boolean evict = false; - boolean deepValidate = true; - Set validatedFields = null; - List validatedFieldsList = null; - - if (arguments.length > 0) { - if (arguments[0] instanceof Boolean) { - evict = (Boolean)arguments[0]; - } - if (arguments[0] instanceof Map) { - Map argsMap = (Map)arguments[0]; - - if (argsMap.containsKey(ARGUMENT_DEEP_VALIDATE)) { - deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap); - } - - evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, argsMap); - } - if (arguments[0] instanceof List) { - validatedFieldsList = (List)arguments[0]; - validatedFields = new HashSet(validatedFieldsList); - } - } - - fireEvent(target, validatedFieldsList); - - AbstractPersistentConstraint.sessionFactory.set(datastore.getSessionFactory()); - try { - if (deepValidate && (validator instanceof CascadingValidator)) { - ((CascadingValidator)validator).validate(target, errors, deepValidate); - } - else { - validator.validate(target,errors); - } - } - finally { - AbstractPersistentConstraint.sessionFactory.remove(); - } - - int oldErrorCount = errors.getErrorCount(); - errors = filterErrors(errors, validatedFields, target); - - if (errors.hasErrors()) { - valid = Boolean.FALSE; - if (evict) { - // if an boolean argument 'true' is passed to the method - // and validation fails then the object will be evicted - // from the session, ensuring it is not saved later when - // flush is called - if (getHibernateTemplate().contains(target)) { - getHibernateTemplate().evict(target); - } - } - } - - // If the errors have been filtered, update the 'errors' object attached to the target. - if (errors.getErrorCount() != oldErrorCount) { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - metaClass.setProperty(target, ERRORS_PROPERTY, errors); - } - - return valid; - } - - private void fireEvent(Object target, List<?> validatedFieldsList) { - ValidationEvent event = new ValidationEvent(datastore, target); - event.setValidatedFields(validatedFieldsList); - application.getMainContext().publishEvent(event); - } - - @SuppressWarnings("rawtypes") - private Errors filterErrors(Errors errors, Set validatedFields, Object target) { - if (validatedFields == null) return errors; - - ValidationErrors result = new ValidationErrors(target); - - final List allErrors = errors.getAllErrors(); - for (Object allError : allErrors) { - ObjectError error = (ObjectError) allError; - - if (error instanceof FieldError) { - FieldError fieldError = (FieldError) error; - if (!validatedFields.contains(fieldError.getField())) continue; - } - - result.addError(error); - } - - return result; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java new file mode 100644 index 0000000..1059dcd --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java
@@ -0,0 +1,41 @@ +/* + * Copyright 2014 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.codehaus.groovy.grails.orm.hibernate.proxy; + +import org.hibernate.mapping.PersistentClass; +import org.hibernate.property.Getter; +import org.hibernate.property.Setter; +import org.hibernate.proxy.ProxyFactory; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.tuple.entity.PojoEntityTuplizer; + +/** + * Ensures a Groovy aware proxy factory is registered + * + * @author Graeme Rocher + * @since 4.0 + */ +public class GroovyAwarePojoEntityTuplizer extends PojoEntityTuplizer { + + public GroovyAwarePojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { + super(entityMetamodel, mappedEntity); + } + + @Override + protected ProxyFactory buildProxyFactoryInternal(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { + return new GroovyAwareJavassistProxyFactory(); + } +}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java index be752f0..bf8ffe5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java
@@ -16,15 +16,8 @@ package org.codehaus.groovy.grails.orm.hibernate.proxy; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.support.proxy.EntityProxyHandler; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Hibernate; import org.hibernate.collection.AbstractPersistentCollection; import org.hibernate.collection.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.HibernateProxyHelper; -import org.hibernate.proxy.LazyInitializer; /** * Implementation of the ProxyHandler interface for Hibernate. @@ -32,96 +25,36 @@ * @author Graeme Rocher * @since 1.2.2 */ -public class HibernateProxyHandler implements EntityProxyHandler { +public class HibernateProxyHandler extends SimpleHibernateProxyHandler { public boolean isInitialized(Object o) { - if (o instanceof HibernateProxy) { - return !((HibernateProxy)o).getHibernateLazyInitializer().isUninitialized(); - } - if (o instanceof PersistentCollection) { return ((PersistentCollection)o).wasInitialized(); } - return true; - } - - public boolean isInitialized(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); - return Hibernate.isInitialized(proxy); - } - catch (RuntimeException e) { - return false; - } + return super.isInitialized(o); } public Object unwrapIfProxy(Object instance) { - if (instance instanceof HibernateProxy) { - final HibernateProxy proxy = (HibernateProxy)instance; - return unwrapProxy(proxy); - } - if (instance instanceof AbstractPersistentCollection) { initialize(instance); return instance; } - return instance; - } - - public Object unwrapProxy(final HibernateProxy proxy) { - final LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer(); - if (lazyInitializer.isUninitialized()) { - lazyInitializer.initialize(); - } - final Object obj = lazyInitializer.getImplementation(); - if (obj != null) { - GrailsHibernateUtil.ensureCorrectGroovyMetaClass(obj,obj.getClass()); - } - return obj; - } - - public HibernateProxy getAssociationProxy(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (RuntimeException e) { - return null; - } + return super.unwrapIfProxy(instance); } public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (o instanceof AbstractPersistentCollection); + return super.isProxy(o) || (o instanceof AbstractPersistentCollection); } public void initialize(Object o) { - if (o instanceof HibernateProxy) { - final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer(); - if (hibernateLazyInitializer.isUninitialized()) { - hibernateLazyInitializer.initialize(); - } - } - else if (o instanceof AbstractPersistentCollection) { + if (o instanceof AbstractPersistentCollection) { final AbstractPersistentCollection col = (AbstractPersistentCollection)o; if (!col.wasInitialized()) { col.forceInitialization(); } } - } - - public Object getProxyIdentifier(Object o) { - if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); - } - return null; - } - - public Class<?> getProxiedClass(Object o) { - return HibernateProxyHelper.getClassWithoutInitializingProxy(o); + super.initialize(o); } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java index 27149c7..0418349 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java
@@ -28,11 +28,11 @@ import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.grails.commons.GrailsClassUtils; import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormValidationApi; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; import org.grails.datastore.gorm.support.BeforeValidateHelper.BeforeValidateEventTriggerCaller; import org.grails.datastore.gorm.support.EventTriggerCaller; @@ -90,7 +90,7 @@ Map validateParams; MetaMethod validateMethod; TimestampProvider timestampProvider; - + public ClosureEventListener(Class<?> domainClazz, boolean failOnError, List failOnErrorPackages) { this(domainClazz, failOnError, failOnErrorPackages, new DefaultTimestampProvider()); } @@ -122,11 +122,11 @@ } validateParams = new HashMap(); - validateParams.put(ValidatePersistentMethod.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); + validateParams.put(AbstractHibernateGormValidationApi.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); - errorsProperty = domainMetaClass.getMetaProperty(AbstractDynamicPersistentMethod.ERRORS_PROPERTY); + errorsProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.ERRORS); - validateMethod = domainMetaClass.getMetaMethod(ValidatePersistentMethod.METHOD_SIGNATURE, + validateMethod = domainMetaClass.getMetaMethod("validate", new Object[] { Map.class }); try { @@ -155,7 +155,7 @@ shouldTimestamp = false; } } - + private boolean verifyTimestampFieldTypeSupport(Class<?> domainClazz, TimestampProvider timestampProvider, MetaProperty timestampField) { if(timestampProvider.supportsCreating(timestampField.getType())) { return true; @@ -253,7 +253,7 @@ public void onPostInsert(PostInsertEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postInsertEventListener == null) { return; } @@ -269,7 +269,7 @@ public void onPostUpdate(PostUpdateEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postUpdateEventListener == null) { return; } @@ -285,7 +285,7 @@ public void onPostDelete(PostDeleteEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postDeleteEventListener == null) { return; } @@ -311,7 +311,7 @@ } }); } - + public boolean onPreUpdate(final PreUpdateEvent event) { return doWithManualSession(event, new Closure<Boolean>(this) { @Override @@ -323,7 +323,7 @@ synchronizePersisterState(event, event.getState()); } handleTimestampingBeforeUpdate(event, entity); - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) + if (!AbstractHibernateGormInstanceApi.isAutoValidationDisabled(entity) && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { evict = true; if (failOnErrorEnabled) { @@ -367,7 +367,7 @@ } boolean evict = false; - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) + if (!AbstractHibernateGormInstanceApi.isAutoValidationDisabled(entity) && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { evict = true;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java index dc484ac..4accc47 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java
@@ -18,6 +18,7 @@ import grails.util.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryProxy; import org.codehaus.groovy.grails.orm.hibernate.events.SaveOrUpdateEventListener; @@ -81,7 +82,7 @@ private ApplicationContext ctx; private Map<SessionFactory, HibernateDatastore> datastores; - private static final ThreadLocal<Boolean> insertActiveThreadLocal = new ThreadLocal<Boolean>(); + public ClosureEventTriggeringInterceptor() { try { @@ -322,7 +323,7 @@ */ @Override protected Boolean getAssumedUnsaved() { - return insertActiveThreadLocal.get(); + return AbstractHibernateGormInstanceApi.getAssumedUnsaved(); } /** @@ -330,13 +331,13 @@ * to set a ThreadLocal variable that determines the value for getAssumedUnsaved(). */ public static void markInsertActive() { - insertActiveThreadLocal.set(Boolean.TRUE); + AbstractHibernateGormInstanceApi.markInsertActive(); } /** * Clears the ThreadLocal variable set by markInsertActive(). */ public static void resetInsertActive() { - insertActiveThreadLocal.remove(); + AbstractHibernateGormInstanceApi.resetInsertActive(); } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java index 327db75..b28d9c4 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java
@@ -14,8 +14,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; +import grails.web.mapping.mvc.RedirectEventListener; import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.web.servlet.mvc.RedirectEventListener; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java index bd5dba9..40adc5a 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java
@@ -14,13 +14,10 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest; -import org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse; +import org.grails.web.servlet.mvc.GrailsWebRequest; import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; @@ -95,19 +92,6 @@ return; } - GrailsWebRequest webRequest = (GrailsWebRequest) request; - HttpServletResponse response = webRequest.getCurrentResponse(); - GrailsContentBufferingResponse contentBufferingResponse = getContentBufferingResponse(response); - if (contentBufferingResponse == null) { - super.afterCompletion(request, ex); - return; - } - - // if Sitemesh is still active disconnect the session, but don't close the session - if (!contentBufferingResponse.isActive()) { - super.afterCompletion(request, ex); - return; - } try { Session session = SessionFactoryUtils.getSession(getSessionFactory(), false); @@ -119,20 +103,10 @@ super.afterCompletion(request, ex); } } finally { - AbstractSavePersistentMethod.clearDisabledValidations(); + AbstractHibernateGormInstanceApi.clearDisabledValidations(); } } - private GrailsContentBufferingResponse getContentBufferingResponse(HttpServletResponse response) { - while(response instanceof HttpServletResponseWrapper) { - if (response instanceof GrailsContentBufferingResponse) { - return (GrailsContentBufferingResponse) response; - } - response = (HttpServletResponse) ((HttpServletResponseWrapper) response).getResponse(); - } - return null; - } - @Override protected void flushIfNecessary(Session session, boolean existingTransaction) throws HibernateException { if (session != null && !FlushMode.isManualFlushMode(session.getFlushMode())) {
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java index e34d374..9214eff 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java
@@ -15,6 +15,9 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; +import grails.config.Config; +import grails.core.GrailsApplication; +import grails.core.support.GrailsApplicationAware; import groovy.util.ConfigObject; import java.sql.Connection; @@ -22,9 +25,7 @@ import javax.sql.DataSource; -import org.codehaus.groovy.grails.commons.GrailsApplication; import org.codehaus.groovy.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException; -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware; import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.resolver.DialectFactory; @@ -79,7 +80,7 @@ connection = DataSourceUtils.getConnection(dataSource); try { - ConfigObject config = grailsApplication != null ? grailsApplication.getConfig() : null; + Config config = grailsApplication != null ? grailsApplication.getConfig() : null; Properties properties = config != null ? config.toProperties() : new Properties(); hibernateDialect = DialectFactory.buildDialect(properties, connection); hibernateDialectClassName = hibernateDialect.getClass().getName();
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java index 0a55366..5b8b9d7 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java
@@ -15,14 +15,14 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; +import grails.core.GrailsDomainClassProperty; +import grails.persistence.support.PersistenceContextInterceptor; import grails.validation.DeferredBindingActions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; +import org.grails.core.lifecycle.ShutdownOperations; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory; @@ -98,7 +98,7 @@ LOG.error("Unexpected exception on closing Hibernate Session", ex); } } finally { - AbstractSavePersistentMethod.clearDisabledValidations(); + AbstractHibernateGormInstanceApi.clearDisabledValidations(); } }
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java deleted file mode 100644 index c57cdcb..0000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java +++ /dev/null
@@ -1,93 +0,0 @@ -/* Copyright 2004-2005 Graeme Rocher - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.validation; - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.validation.AbstractConstraint; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.orm.hibernate3.HibernateTemplate; - -/** - * Constraints that require access to the HibernateTemplate should subclass this class. - * - * @author Graeme Rocher - * @since 0.4 - */ -public abstract class AbstractPersistentConstraint extends AbstractConstraint implements PersistentConstraint { - - public static ThreadLocal<SessionFactory> sessionFactory = new ThreadLocal<SessionFactory>(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - sessionFactory.remove(); - } - }); - } - - protected ApplicationContext applicationContext; - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - public HibernateTemplate getHibernateTemplate() { - SessionFactory sf = sessionFactory.get(); - if (sf == null) { - sf = applicationContext.getBean("sessionFactory", SessionFactory.class); - } - GrailsApplication app = applicationContext.getBean("grailsApplication", GrailsApplication.class); - GrailsHibernateTemplate hibernateTemplate = new GrailsHibernateTemplate(sf, app, GrailsHibernateTemplate.FLUSH_NEVER); - hibernateTemplate.setAllowCreate(true); - return hibernateTemplate; - } - - /** - * Returns whether the constraint supports being applied against the specified type; - * - * @param type The type to support - * @return true if the constraint can be applied against the specified type - */ - public boolean supports(@SuppressWarnings("rawtypes") Class type) { - return true; - } - - /** - * Return whether the constraint is valid for the owning class - * - * @return true if it is - */ - public boolean isValid() { - if (applicationContext.containsBean("sessionFactory")) { - GrailsApplication grailsApplication = applicationContext.getBean( - GrailsApplication.APPLICATION_ID, GrailsApplication.class); - GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact( - DomainClassArtefactHandler.TYPE, constraintOwningClass.getName()); - if (domainClass != null) { - String mappingStrategy = domainClass.getMappingStrategy(); - return mappingStrategy.equals(GrailsDomainClass.GORM) - || mappingStrategy.equals(GrailsHibernateDomainClass.HIBERNATE); - } - } - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java index 08c5d22..a548018 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java
@@ -16,11 +16,12 @@ import java.util.Map; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClassProperty; +import grails.validation.Constrained; +import grails.validation.ConstrainedProperty; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.PropertyConfig; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -import org.codehaus.groovy.grails.validation.DefaultConstraintEvaluator; +import org.grails.validation.DefaultConstraintEvaluator; /** * Extends default implementation to add Hibernate specific exceptions. @@ -39,7 +40,7 @@ } @Override - protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, ConstrainedProperty cp) { + protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, Constrained cp) { final PropertyConfig propertyConfig = new GrailsDomainBinder().getPropertyConfig(p); boolean insertable = propertyConfig != null ? propertyConfig.isInsertable() : true;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java index 7e125d1..7ca165b 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java
@@ -14,12 +14,12 @@ */ package org.codehaus.groovy.grails.orm.hibernate.validation; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.core.support.proxy.ProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; -import org.codehaus.groovy.grails.support.proxy.ProxyHandler; -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.validation.GrailsDomainClassValidator; import org.hibernate.FlushMode; import org.hibernate.Hibernate; import org.hibernate.SessionFactory;
diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java index 2204f01..b3e21fd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java
@@ -18,18 +18,19 @@ import java.util.Collections; import java.util.List; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.exceptions.GrailsRuntimeException; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.util.GrailsClassUtils; +import grails.validation.ConstrainedProperty; +import groovy.lang.Closure; +import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; +import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; import org.codehaus.groovy.runtime.InvokerHelper; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.core.exceptions.GrailsRuntimeException; +import org.grails.core.lifecycle.ShutdownOperations; +import org.hibernate.*; import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.springframework.beans.BeanWrapper; @@ -146,24 +147,23 @@ "domain classes and not custom user types or embedded instances"); } - HibernateTemplate hibernateTemplate = getHibernateTemplate(); - Assert.state(hibernateTemplate != null, - "Unable use [unique] constraint, no Hibernate SessionFactory found!"); - List<?> results = hibernateTemplate.execute(new HibernateCallback<List<?>>() { - public List<?> doInHibernate(Session session) throws HibernateException { + IHibernateTemplate hibernateTemplate = getHibernateTemplate(); + List<?> results = hibernateTemplate.execute(new Closure<List<?>>(this) { + public List<?> call(Object... args) { + Session session = (Session)args[0]; boolean shouldValidate = true; Class<?> constraintClass = constraintOwningClass; if (propertyValue != null && DomainClassArtefactHandler.isDomainClass(propertyValue.getClass())) { shouldValidate = session.contains(propertyValue); } if (shouldValidate) { - GrailsApplication application = (GrailsApplication) applicationContext.getBean(GrailsApplication.APPLICATION_ID); - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE,constraintClass.getName()); + GrailsApplication application = (GrailsApplication) applicationContext.getBean(GrailsApplication.APPLICATION_ID); + GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, constraintClass.getName()); if (domainClass != null && !domainClass.isRoot()) { GrailsDomainClassProperty property = domainClass.getPropertyByName(constraintPropertyName); while (property.isInherited() && domainClass != null) { domainClass = (GrailsDomainClass) application.getArtefact( - DomainClassArtefactHandler.TYPE,domainClass.getClazz().getSuperclass().getName()); + DomainClassArtefactHandler.TYPE, domainClass.getClazz().getSuperclass().getName()); if (domainClass != null) { property = domainClass.getPropertyByName(constraintPropertyName); } @@ -188,7 +188,7 @@ criteria.add(Restrictions.eq(constraintPropertyAlias + "." + identifierPropertyName, identifierPropertyValue)); } else { criteria = session.createCriteria(constraintClass) - .add(Restrictions.eq(constraintPropertyName, propertyValue)); + .add(Restrictions.eq(constraintPropertyName, propertyValue)); } if (uniquenessGroup != null) { @@ -202,8 +202,7 @@ } if (shouldValidate) { criteria.add(Restrictions.eq(uniquenessGroupPropertyName, uniquenessGroupPropertyValue)); - } - else { + } else { break; // we aren't validating, so no point continuing } } @@ -215,7 +214,7 @@ return Collections.EMPTY_LIST; } return Collections.EMPTY_LIST; - } + } }); if (results.isEmpty()) { @@ -249,4 +248,15 @@ return uniquenessGroup; } + @Override + public IHibernateTemplate getHibernateTemplate() { + SessionFactory sf = sessionFactory.get(); + if (sf == null) { + sf = applicationContext.getBean("sessionFactory", SessionFactory.class); + } + GrailsApplication app = applicationContext.getBean("grailsApplication", GrailsApplication.class); + GrailsHibernateTemplate hibernateTemplate = new GrailsHibernateTemplate(sf, app, GrailsHibernateTemplate.FLUSH_NEVER); + hibernateTemplate.setAllowCreate(true); + return hibernateTemplate; + } }
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy index 54d0755..e1d0c83 100755 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy
@@ -1,8 +1,8 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication import grails.gorm.tests.GormDatastoreSpec import junit.framework.Assert -import org.codehaus.groovy.grails.commons.GrailsApplication import org.grails.datastore.mapping.core.DatastoreUtils import org.hibernate.Session import org.hibernate.SessionFactory
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy index 4a993d6..1dc5ef0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.* /**
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy index 1dac0a7..515f640 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication +import grails.core.DefaultGrailsApplication import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration import org.hibernate.FetchMode import org.hibernate.engine.CascadeStyle
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy index 0daf708..639107a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy index 54c8dfe..4d1d29b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy index 6b9dcdd..21efb82 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy index 75c4869..5b6ca1d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy index e49edb8..1f49801 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy index 0c2ebb2..d608071 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate import grails.gorm.tests.Plant -import org.codehaus.groovy.grails.web.util.StreamCharBuffer +import org.grails.buffer.StreamCharBuffer import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy index 87e87ec..a80ad14 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy
@@ -76,9 +76,12 @@ } } +trait SomeTrait { + void foo(){} +} @Entity -class CompositeIdentifierWithAssociationsParent implements Serializable { +class CompositeIdentifierWithAssociationsParent implements Serializable, SomeTrait { Long id Long version @@ -118,4 +121,4 @@ String postCode CompositeIdentifierWithAssociationsParent parent static belongsTo = [parent:CompositeIdentifierWithAssociationsParent] -} \ No newline at end of file +}
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy index 9cf1acc..cd6974f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy
@@ -1,9 +1,9 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty import org.hibernate.id.IdentifierGenerationException import org.springframework.orm.hibernate3.HibernateSystemException
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy index 48121f0..9566cb7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy
@@ -1,7 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass - +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy index d28511b..5f995b2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication import grails.gorm.tests.GormDatastoreSpec -import org.codehaus.groovy.grails.commons.GrailsApplication import org.hibernate.SessionFactory import org.springframework.context.ApplicationContext import spock.lang.Shared
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy index f793bf3..7885dc8 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy
@@ -1,11 +1,9 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.orm.HibernateCriteriaBuilder import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass - +import org.grails.core.artefact.DomainClassArtefactHandler import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy index a0df03f..2c1e235 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy
@@ -1,7 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import grails.persistence.Entity - +import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id import javax.persistence.JoinColumn
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy index 5cd2994..e4527ac 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.apache.commons.beanutils.PropertyUtils import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil +import org.grails.core.util.ClassPropertyFetcher import org.hibernate.Hibernate import org.hibernate.proxy.HibernateProxy @@ -19,6 +19,7 @@ @Test void testDynamicMethodOnProxiedObject() { + def cpf = ClassPropertyFetcher.forClass(LazyLoadedUserIdentifier) def user = LazyLoadedUser.newInstance(name:"Fred") assertNotNull user.save(flush:true) @@ -29,7 +30,7 @@ session.clear() id = LazyLoadedUserIdentifier.get(1) - def proxy = PropertyUtils.getProperty(id, "user") + def proxy = cpf.getPropertyValue(id, "user") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", Hibernate.isInitialized(proxy) assertNotNull "calling save() on the proxy should have worked",proxy.save() @@ -37,6 +38,7 @@ @Test void testMethodCallsOnProxiedObjects() { + def cpf = ClassPropertyFetcher.forClass(LazyLoadedUserIdentifier) def user = LazyLoadedUser.newInstance(name:"Fred") assertNotNull user.save(flush:true) @@ -47,7 +49,7 @@ id = LazyLoadedUserIdentifier.get(1) - def proxy = PropertyUtils.getProperty(id, "user") + def proxy = cpf.getPropertyValue(id, "user") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", Hibernate.isInitialized(proxy) assertEquals "Fred", proxy.name
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy index 806d86d..6404ec3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy
@@ -1,8 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate import grails.persistence.Entity - -import org.apache.commons.beanutils.PropertyUtils +import org.grails.core.util.ClassPropertyFetcher import org.hibernate.proxy.HibernateProxy import static junit.framework.Assert.* @@ -30,6 +29,7 @@ @Test void testMethodCallsOnProxiedObjects() { + def cpf = ClassPropertyFetcher.forClass(LazyProxiedAssociationsWithInheritanceBook) def addr = LazyProxiedAssociationsWithInheritanceAddress.newInstance(houseNumber:'52') def auth = LazyProxiedAssociationsWithInheritanceAuthor.newInstance(name:'Marc Palmer') assertNotNull addr.save() @@ -44,7 +44,7 @@ session.clear() book = LazyProxiedAssociationsWithInheritanceBook.get(1) - def proxy = PropertyUtils.getProperty(book, "author") + def proxy = cpf.getPropertyValue(book, "author") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", org.hibernate.Hibernate.isInitialized(proxy) @@ -61,6 +61,7 @@ @Test void testSettersOnProxiedObjects() { + def cpf = ClassPropertyFetcher.forClass(LazyProxiedAssociationsWithInheritanceBook) def Author = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceAuthor.name).clazz def Address = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceAddress.name).clazz def Book = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceBook.name).clazz @@ -80,7 +81,7 @@ book = Book.get(1) - def proxy = PropertyUtils.getProperty(book, "author") + def proxy = cpf.getPropertyValue(book, "author") // test setter with non-null value proxy.address.houseNumber = '123' book.save() @@ -96,7 +97,7 @@ // test setting property to null book = Book.get(1) - proxy = PropertyUtils.getProperty(book, "author") + proxy = cpf.getPropertyValue(book, "author") proxy.address.houseNumber = null book.save() @@ -111,7 +112,7 @@ // should delegate call to the closure defined in HibernatePluginSupport.enhanceProxy // this broke with previous code book = Book.get(1) - proxy = PropertyUtils.getProperty(book, "author") + proxy = cpf.getPropertyValue(book, "author") proxy.address = null book.save() session.flush()
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy index d5035cc..b2c60d2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy
@@ -1,6 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass + import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy index ed7286e..5e93b2c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy index f519e88..57b1c57 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy
@@ -1,10 +1,8 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder -import org.codehaus.groovy.grails.plugins.GrailsPlugin -import org.codehaus.groovy.grails.validation.ConstrainedProperty import org.hibernate.type.YesNoType import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/NamedCriteriaTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/NamedCriteriaTests.groovy index 3e40cd9..97ebded 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/NamedCriteriaTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/NamedCriteriaTests.groovy
@@ -3,6 +3,7 @@ import grails.orm.PagedResultList import org.hibernate.NonUniqueResultException +import org.junit.Ignore import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy index 7fe0c03..baca56e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy
@@ -1,6 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass + import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy index cac450e..76e6e70 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy
@@ -1,12 +1,11 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByPersistentMethod import org.codehaus.groovy.runtime.metaclass.MethodSelectionException +import org.grails.core.artefact.DomainClassArtefactHandler import org.springframework.core.convert.ConversionFailedException import org.springframework.validation.Errors @@ -24,15 +23,6 @@ } @Test - void testMethodSignatures() { - FindByPersistentMethod findBy = new FindByPersistentMethod(grailsApplication.mainContext.hibernateDatastore, - grailsApplication, sessionFactory, new GroovyClassLoader()) - assertTrue findBy.isMethodMatch("findByFirstName") - assertTrue findBy.isMethodMatch("findByFirstNameAndLastName") - assertFalse findBy.isMethodMatch("rubbish") - } - - @Test void testSavePersistentMethod() { // init spring config @@ -317,7 +307,7 @@ assertEquals 1, returnList.size() // and case when automatic conversion cannot be applied - shouldFail(ConversionFailedException) { + shouldFail(MissingMethodException) { returnList = domainClass.findAllById("1.1") } @@ -606,14 +596,14 @@ // test find with max result namedArgs.clear() namedArgs.namesList = ["wilma","fred"] as Object[] - returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, [max:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue assertEquals 1, listResult.size() // test find with max result without params - returnValue = domainClass.findAll("from PersistentMethodTests as p", 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p", [max:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -643,7 +633,7 @@ // test find with offset namedArgs.clear() namedArgs.namesList = ["wilma","fred"] as Object[] - returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, 2, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, [max:1, offset:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -651,7 +641,7 @@ assertEquals 1, listResult.size() // test find with offset without params - returnValue = domainClass.findAll("from PersistentMethodTests as p", 2, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p", [max:1, offset:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -783,12 +773,12 @@ domainClass.executeQuery() } - shouldFail(MissingMethodException) { + shouldFail(IllegalArgumentException) { domainClass.executeQuery("query", "param", [:], "4") } // test query with wrong third param type (must be Map) - shouldFail(MissingMethodException) { + shouldFail(IllegalArgumentException) { domainClass.executeQuery("query", "param", "wrong third param") } @@ -863,10 +853,6 @@ assertEquals 1, listResult.size() assertEquals "fred", listResult[0].getProperty("firstName") - def msg = shouldFail(IllegalArgumentException) { - domainClass.executeQuery 'select distinct p from PersistentMethodTests as p where p.firstName = :firstName and p.lastName = :lastName', [firstName: null, lastName: 'King'] - } - assertEquals 'Named parameter [firstName] value may not be null', msg // Test that executeQuery does not mutate List and Map arguments (GRAILS-7841) paginateParams = [max: 1]
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy index 75e1e2c..a4a9d07 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy
@@ -142,7 +142,6 @@ Long version String name - Set unibooks Set books static hasMany = [books:SortMappingBook] @@ -174,7 +173,6 @@ Long version String name - Set unibooks Set books static hasMany = [books:SortMappingBook2]
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy index 90e2235..baa7736 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy index e755679..af22ce6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy
@@ -22,7 +22,7 @@ a.addToBooks(MappedU2mBook.newInstance(title:"The Shining")) .addToBooks(MappedU2mBook.newInstance(title:"The Stand")) - .save(true) + .save(flush:true) assertEquals 2, MappedU2mBook.list().size() // now let's test the database state
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy index 1c37eb0..5cb7205 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication +import grails.core.DefaultGrailsApplication import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration /**
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy index 26c4201..e9b4f8f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy
@@ -49,7 +49,7 @@ Long version String name Set books - def relatesToMany = [books:WithCriteriaMethodBook] + static hasMany = [books:WithCriteriaMethodBook] boolean equals(obj) { name == obj?.name } int hashCode() { name ? name.hashCode() : super.hashCode() } String toString() { name }
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy index 4675335..27a6dc2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy
@@ -15,20 +15,21 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg +import grails.core.DefaultGrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.plugins.GrailsPlugin +import grails.plugins.GrailsPluginManager +import grails.util.Holders +import grails.validation.ConstrainedProperty +import org.codehaus.groovy.grails.validation.TestClass +import org.grails.core.DefaultGrailsDomainClass +import org.grails.plugins.MockGrailsPluginManager +import org.grails.support.MockApplicationContext import org.junit.Ignore import java.lang.reflect.Field -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.codehaus.groovy.grails.plugins.MockGrailsPluginManager -import org.codehaus.groovy.grails.plugins.PluginManagerHolder -import org.codehaus.groovy.grails.support.MockApplicationContext -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.codehaus.groovy.grails.validation.TestClass import org.hibernate.cfg.ImprovedNamingStrategy import org.hibernate.mapping.Bag import org.hibernate.mapping.Column @@ -245,7 +246,7 @@ super.setUp() ExpandoMetaClass.enableGlobally() MockGrailsPluginManager pluginManager = new MockGrailsPluginManager() - PluginManagerHolder.setPluginManager(pluginManager) + Holders.setPluginManager(pluginManager) previousNamingStrategyClass = grailsDomainBinder.NAMING_STRATEGIES[GrailsDomainClassProperty.DEFAULT_DATA_SOURCE].getClass() } @@ -255,7 +256,7 @@ grailsDomainBinder.NAMING_STRATEGIES.clear() grailsDomainBinder.NAMING_STRATEGIES.put( GrailsDomainClassProperty.DEFAULT_DATA_SOURCE, ImprovedNamingStrategy.INSTANCE) - PluginManagerHolder.setPluginManager(null) + Holders.setPluginManager(null) grailsDomainBinder.configureNamingStrategy previousNamingStrategyClass } @@ -856,11 +857,11 @@ def myPluginMap = [:] myPluginMap.getName = { -> 'MyPlugin' } - def myPlugin = myPluginMap as org.codehaus.groovy.grails.plugins.GrailsPlugin + def myPlugin = myPluginMap as GrailsPlugin def publisherPluginMap = [:] publisherPluginMap.getName = { -> 'Publisher' } - def publisherPlugin = publisherPluginMap as org.codehaus.groovy.grails.plugins.GrailsPlugin + def publisherPlugin = publisherPluginMap as GrailsPlugin def pluginManagerMap = [setApplicationContext: { }] def myPluginDomainClassNames = ['GadgetClass', 'MyPluginPersonClass'] @@ -879,7 +880,7 @@ // no config property specified def cfg = new ConfigSlurper().parse(''' ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) def config = getDomainConfig(grailsApplication, pluginManager) def persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -894,7 +895,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.table.prefix.enabled = true ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -909,7 +910,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.table.prefix.enabled = false ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -924,7 +925,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.publisher.table.prefix.enabled = true ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -940,7 +941,7 @@ grails.gorm.table.prefix.enabled = true grails.gorm.myPlugin.table.prefix.enabled = false ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name)
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy deleted file mode 100644 index e706bc0..0000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy +++ /dev/null
@@ -1,45 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.metaclass - -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.orm.hibernate.Customer -import org.codehaus.groovy.grails.orm.hibernate.GormSpec -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore -import org.grails.datastore.mapping.model.MappingContext -import org.hibernate.Criteria -import org.hibernate.SessionFactory -import org.hibernate.impl.CriteriaImpl - -import spock.lang.Issue - -class AbstractFindByPersistentMethodSpec extends GormSpec { - - @Issue('GRAILS-8762') - void "Test that findBy configures a limit of 1"() { - given:"A finder method" - final datastore = new HibernateDatastore(applicationContext.getBean(MappingContext), sessionFactory, grailsApplication.config) - datastore.applicationContext = applicationContext - def finder = new TestFindBy(datastore, grailsApplication) - when:"The finder is invoked" - CriteriaImpl c = finder.invoke(Customer, "findByName", "Bob") - - then: "ensure that the limit is one" - c.maxResults == 1 - } - - @Override - List getDomainClasses() { - [Customer] - } -} - -class TestFindBy extends AbstractFindByPersistentMethod { - - TestFindBy(HibernateDatastore datastore, GrailsApplication application) { - super(datastore, application, datastore.getSessionFactory(), Thread.currentThread().contextClassLoader, ~/(findBy)([A-Z]\w*)/, ["Or", "And"] as String[]) - } - - @Override - protected Object getResult(Criteria crit, boolean useLimit) { - return crit - } -}
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormTransformerSpec.groovy similarity index 92% rename from grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormTransformerSpec.groovy index 35a5e67..be990a9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormTransformerSpec.groovy
@@ -1,12 +1,13 @@ -package org.codehaus.groovy.grails.compiler.gorm +package org.grails.compiler.gorm +import grails.compiler.ast.ClassInjector import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.DefaultGrailsDomainClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader import org.codehaus.groovy.control.MultipleCompilationErrorsException +import org.grails.compiler.gorm.GormTransformer; +import org.grails.compiler.injection.DefaultGrailsDomainClassInjector +import org.grails.compiler.injection.GrailsAwareClassLoader +import org.grails.core.DefaultGrailsDomainClass import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.GormValidationApi @@ -14,8 +15,8 @@ import org.springframework.validation.Errors import spock.lang.Specification -import org.codehaus.groovy.grails.commons.spring.GrailsApplicationContext import grails.spring.BeanBuilder + import org.springframework.context.ConfigurableApplicationContext class GormTransformerSpec extends Specification {
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormValidationTransformerSpec.groovy similarity index 85% rename from grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormValidationTransformerSpec.groovy index ae6c64f..578f099 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/GormValidationTransformerSpec.groovy
@@ -1,7 +1,9 @@ -package org.codehaus.groovy.grails.compiler.gorm +package org.grails.compiler.gorm -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader +import grails.compiler.ast.ClassInjector + +import org.grails.compiler.gorm.GormValidationTransformer; +import org.grails.compiler.injection.GrailsAwareClassLoader import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormValidationApi import org.grails.datastore.mapping.simple.SimpleMapDatastore
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/SessionFactoryProxySpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/SessionFactoryProxySpec.groovy index 8c1e7ef..b2ff890 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/compiler/gorm/SessionFactoryProxySpec.groovy
@@ -1,4 +1,4 @@ -package org.codehaus.groovy.grails.compiler.gorm +package org.grails.compiler.gorm import grails.spring.BeanBuilder
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy index 542136a..1d5bfc4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy
@@ -7,6 +7,8 @@ import grails.gorm.tests.CrudOperationsSpec import grails.gorm.tests.DetachedCriteriaSpec import grails.gorm.tests.DomainEventsSpec +import grails.gorm.tests.EnumSpec +import grails.gorm.tests.FindByExampleSpec import grails.gorm.tests.FindByMethodSpec import grails.gorm.tests.FindWhereSpec import grails.gorm.tests.GormEnhancerSpec @@ -61,6 +63,7 @@ // OneToOneSpec // FindWhereSpec //DetachedCriteriaSpec -SizeQuerySpec +//SizeQuerySpec + FindByExampleSpec ]) class HibernateSuite {}
diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy index 691423f..a95490d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy
@@ -1,12 +1,11 @@ package org.grails.datastore.gorm +import grails.core.DefaultGrailsApplication import groovy.sql.Sql +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.validation.ConstrainedProperty import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.metaclass.MetaClassEnhancer import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore import org.codehaus.groovy.grails.orm.hibernate.HibernateGormEnhancer @@ -18,7 +17,9 @@ import org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import org.grails.core.metaclass.MetaClassEnhancer + +//import org.codehaus.groovy.grails.plugins.web.api.ControllersDomainBindingApi import org.grails.datastore.gorm.config.GrailsDomainClassMappingContext import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.MappingContext @@ -88,14 +89,14 @@ try { sql?.close() } catch (ignored) {} } } - + static Session setup(List<Class> classes, ConfigObject grailsConfig = null, boolean isTransactional = true) { ExpandoMetaClass.enableGlobally() // Log4jConfigurer.initLogging("classpath:log4j.properties") grailsApplication = new DefaultGrailsApplication(classes as Class[], new GroovyClassLoader(Setup.getClassLoader())) if(grailsConfig) { - grailsApplication.config.putAll(grailsConfig) + grailsApplication.config.merge(grailsConfig) } applicationContext = new GenericApplicationContext() @@ -176,6 +177,7 @@ def validator = new HibernateDomainClassValidator() + validator.sessionFactory = sessionFactory validator.grailsApplication = grailsApplication validator.domainClass = dc
diff --git a/grails-datastore-gorm-hibernate4/build.gradle b/grails-datastore-gorm-hibernate4/build.gradle index 6e8fd5e..a6841dd 100644 --- a/grails-datastore-gorm-hibernate4/build.gradle +++ b/grails-datastore-gorm-hibernate4/build.gradle
@@ -15,6 +15,12 @@ optional("org.grails:grails-web:$grailsVersion") { transitive = false } + optional("org.grails:grails-web-common:$grailsVersion") { + transitive = false + } + optional("org.grails:grails-web-url-mappings:$grailsVersion") { + transitive = false + } optional("org.grails:grails-spring:$grailsVersion") { transitive = false } @@ -136,4 +142,4 @@ if (!isTravisBuild) { forkEvery = 30 } -} \ No newline at end of file +}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy index 2c2eac1..53914a4 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy
@@ -14,9 +14,11 @@ */ package grails.orm.bootstrap +import grails.core.GrailsApplication +import grails.core.GrailsDomainClassProperty +import grails.util.Environment import groovy.transform.CompileStatic import groovy.util.logging.Commons -import org.codehaus.groovy.grails.commons.GrailsApplication import org.codehaus.groovy.grails.orm.hibernate.* import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler @@ -49,7 +51,7 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { public static final String SESSION_FACTORY_BEAN_NAME = "sessionFactory" - String defaultDataSourceBeanName = "dataSource" + String defaultDataSourceBeanName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE String defaultSessionFactoryBeanName = SESSION_FACTORY_BEAN_NAME String ddlAuto = "update" Set<String> dataSources = [defaultDataSourceBeanName] @@ -72,11 +74,11 @@ super(persistentClasses.toList()) } - HibernateDatastoreSpringInitializer(Properties hibernateProperties, Collection<Class> persistentClasses) { + HibernateDatastoreSpringInitializer(Map hibernateProperties, Collection<Class> persistentClasses) { super(hibernateProperties, persistentClasses) } - HibernateDatastoreSpringInitializer(Properties hibernateProperties, Class... persistentClasses) { + HibernateDatastoreSpringInitializer(Map hibernateProperties, Class... persistentClasses) { super(hibernateProperties, persistentClasses.toList()) } @@ -84,7 +86,7 @@ ApplicationContext configureForDataSource(DataSource dataSource) { ExpandoMetaClass.enableGlobally() GenericApplicationContext applicationContext = new GenericApplicationContext() - applicationContext.beanFactory.registerSingleton(defaultDataSourceBeanName, dataSource) + applicationContext.beanFactory.registerSingleton("dataSource", dataSource) configureForBeanDefinitionRegistry(applicationContext) applicationContext.refresh() return applicationContext @@ -152,7 +154,7 @@ // Used to detect the database dialect to use if(noDialect) { "dialectDetector$suffix"(HibernateDialectDetectorFactoryBean) { - dataSource = ref(dataSourceName) + dataSource = ref("dataSource$suffix") vendorNameDialectMappings = vendorToDialect } } @@ -168,17 +170,21 @@ } + if (Environment.current.isReloadEnabled()) { + "${SessionFactoryHolder.BEAN_ID}$suffix"(SessionFactoryHolder) + } + // the main SessionFactory bean if(!beanDefinitionRegistry.containsBeanDefinition(sessionFactoryName)) { "$sessionFactoryName"(ConfigurableLocalSessionFactoryBean) { bean -> bean.autowire = "byType" - dataSource = ref(dataSourceName) + dataSource = ref("dataSource$suffix") delegate.hibernateProperties = ref("hibernateProperties$suffix") grailsApplication = ref(GrailsApplication.APPLICATION_ID) entityInterceptor = ref("entityInterceptor$suffix") List hibConfigLocations = [] - def cl = classLoader ?: Thread.currentThread().contextClassLoader + def cl = Thread.currentThread().contextClassLoader if (cl.getResource(prefix + 'hibernate.cfg.xml')) { hibConfigLocations << 'classpath:' + prefix + 'hibernate.cfg.xml' } @@ -208,7 +214,7 @@ "transactionManager$suffix"(GrailsHibernateTransactionManager) { bean -> bean.autowire = "byName" sessionFactory = ref(sessionFactoryName) - dataSource = ref(dataSourceName) + dataSource = ref("dataSource$suffix") } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/plugin/hibernate4/HibernatePluginSupport.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/plugin/hibernate4/HibernatePluginSupport.groovy index b088c90..375537b 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/plugin/hibernate4/HibernatePluginSupport.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/plugin/hibernate4/HibernatePluginSupport.groovy
@@ -15,12 +15,12 @@ */ package grails.plugin.hibernate4 -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.commons.spring.DefaultRuntimeSpringConfiguration -import org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator -import org.codehaus.groovy.grails.commons.spring.RuntimeSpringConfiguration +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.util.Environment +import grails.validation.ConstrainedProperty +import grails.validation.ConstraintsEvaluator import org.codehaus.groovy.grails.orm.hibernate.* import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil @@ -31,9 +31,10 @@ import org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.codehaus.groovy.grails.validation.ConstraintsEvaluator import org.grails.datastore.mapping.model.MappingContext +import org.grails.spring.DefaultRuntimeSpringConfiguration +import org.grails.spring.RuntimeSpringConfiguration +import org.grails.web.servlet.context.support.GrailsRuntimeConfigurator import org.hibernate.EmptyInterceptor import org.hibernate.cfg.ImprovedNamingStrategy import org.slf4j.Logger @@ -261,7 +262,7 @@ hibernateProperties = ref("hibernateProperties$suffix") - grailsApplication = ref("grailsApplication", true) + grailsApplication = ref("grailsApplication") entityInterceptor = ref("entityInterceptor$suffix") @@ -394,7 +395,7 @@ def hibConfig = application.config["hibernate$suffix"] def sessionFactoryReload = hibConfig?.containsKey('reload') ? hibConfig.reload : true - if (sessionFactoryReload) { + if (sessionFactoryReload && Environment.current.isReloadEnabled()) { "${SessionFactoryHolder.BEAN_ID}$suffix"(SessionFactoryHolder) { sessionFactory = bean(ConfigurableLocalSessionFactoryBean) { bean -> bean.parent = ref("abstractSessionFactoryBeanConfig$suffix")
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java index cc95352..a9dcedd 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java
@@ -15,6 +15,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClassProperty; import groovy.lang.GroovySystem; import groovy.lang.MetaClassRegistry; @@ -28,8 +30,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration; import org.codehaus.groovy.grails.orm.hibernate.transaction.GrailsJdbcTransactionFactory; import org.hibernate.HibernateException;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java index f9b211b..135a263 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java
@@ -15,6 +15,8 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.config.Config; +import grails.core.GrailsDomainClass; import groovy.lang.GroovySystem; import groovy.util.ConfigObject; @@ -22,14 +24,13 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.codehaus.groovy.grails.commons.AnnotationDomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventListener; import org.codehaus.groovy.grails.orm.hibernate.support.SoftKey; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.grails.core.artefact.AnnotationDomainClassArtefactHandler; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.gorm.timestamp.DefaultTimestampProvider; import org.grails.datastore.gorm.timestamp.TimestampProvider; import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; @@ -63,10 +64,10 @@ private TimestampProvider timestampProvider = new DefaultTimestampProvider(); - public EventTriggeringInterceptor(HibernateDatastore datastore, ConfigObject co) { + public EventTriggeringInterceptor(HibernateDatastore datastore, Config co) { super(datastore); - Object failOnErrorConfig = co.flatten().get("grails.gorm.failOnError"); + Object failOnErrorConfig = co.getProperty("grails.gorm.failOnError", Object.class); if (failOnErrorConfig instanceof List) { failOnError = true; failOnErrorPackages = (List<?>)failOnErrorConfig; @@ -248,5 +249,5 @@ public void setTimestampProvider(TimestampProvider timestampProvider) { this.timestampProvider = timestampProvider; - } + } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java index c6bfb47..c0bbb3a 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java
@@ -17,7 +17,7 @@ import java.util.Collection; -import org.codehaus.groovy.grails.commons.GrailsApplication; +import grails.core.GrailsApplication; import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SessionFactoryImplementor;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java index f35b0f0..1f93f7b 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java
@@ -15,10 +15,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.core.GrailsApplication; +import groovy.lang.Closure; +import groovy.util.ProxyGenerator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.GrailsApplication; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.hibernate.*; import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; @@ -104,16 +107,25 @@ this.flushMode = defaultFlushMode; } + + @Override + public <T> T execute(Closure<T> callable) { + HibernateCallback<T> hibernateCallback = DefaultGroovyMethods.asType(callable, HibernateCallback.class); + return execute(hibernateCallback); + } + public SessionFactory getSessionFactory() { return sessionFactory; } + @Override public void applySettings(Query query) { if (exposeNativeSession) { prepareQuery(query); } } + @Override public void applySettings(Criteria criteria) { if (exposeNativeSession) { prepareCriteria(criteria);
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java index bbe52d8..1596b74 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java
@@ -14,12 +14,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate; +import grails.config.Config; +import grails.core.GrailsApplication; +import grails.core.support.GrailsApplicationAware; import groovy.util.ConfigObject; import java.util.Map; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.MappingContext; import org.hibernate.SessionFactory; @@ -38,15 +39,15 @@ private GrailsApplication grailsApplication; private int defaultFlushMode; - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config) { super(mappingContext, sessionFactory, config); } - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { + + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config, ApplicationContext applicationContext) { this(mappingContext, sessionFactory, config, applicationContext, GrailsHibernateTemplate.FLUSH_AUTO); } - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext, int defaultFlushMode) { + public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, Config config, ApplicationContext applicationContext, int defaultFlushMode) { super(mappingContext, sessionFactory, config, applicationContext); this.defaultFlushMode = defaultFlushMode; }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy index a79f98d..7fd30d6 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.groovy
@@ -14,23 +14,12 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.orm.hibernate.metaclass.CountByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByBooleanPropertyPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByBooleanPropertyPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindOrCreateByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindOrSaveByPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ListOrderByPersistentMethod import org.grails.datastore.gorm.GormInstanceApi import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.PersistentEntity import org.springframework.transaction.PlatformTransactionManager /** @@ -47,19 +36,6 @@ super(datastore, transactionManager, grailsApplication) } - protected List<FinderMethod> createDynamicFinders() { - HibernateDatastore hibernateDatastore = (HibernateDatastore)datastore - def sessionFactory = hibernateDatastore.sessionFactory - [new FindAllByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindAllByBooleanPropertyPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindOrCreateByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindOrSaveByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new FindByBooleanPropertyPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new CountByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader), - new ListOrderByPersistentMethod(hibernateDatastore, grailsApplication, sessionFactory, classLoader)] - } - protected <D> GormValidationApi<D> getValidationApi(Class<D> cls) { new HibernateGormValidationApi<D>(cls, (HibernateDatastore)datastore, classLoader) }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy index 70bb19d..ba8a491 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy
@@ -15,18 +15,13 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil -import org.codehaus.groovy.grails.orm.hibernate.metaclass.MergePersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod -import org.hibernate.LockMode +import org.grails.core.artefact.DomainClassArtefactHandler import org.hibernate.engine.spi.EntityEntry import org.hibernate.engine.spi.SessionImplementor -import org.hibernate.proxy.HibernateProxy -import org.springframework.dao.DataAccessException /** * The implementation of the GORM instance API contract for Hibernate. @@ -37,27 +32,23 @@ @CompileStatic class HibernateGormInstanceApi<D> extends AbstractHibernateGormInstanceApi<D> { - protected SavePersistentMethod saveMethod - protected MergePersistentMethod mergeMethod protected GrailsHibernateTemplate hibernateTemplate protected InstanceApiHelper instanceApiHelper HibernateGormInstanceApi(Class<D> persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) + super(persistentClass, datastore, classLoader, null) def grailsApplication = datastore.getGrailsApplication() if (grailsApplication) { GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.name) config = (Map)grailsApplication.getFlatConfig().get('grails.gorm') - saveMethod = new SavePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) - mergeMethod = new MergePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication, datastore.getDefaultFlushMode()) - cacheQueriesByDefault = GrailsHibernateUtil.isCacheQueriesByDefault(grailsApplication) } else { hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) hibernateTemplate.setFlushMode(datastore.getDefaultFlushMode()) } + super.hibernateTemplate = hibernateTemplate instanceApiHelper = new InstanceApiHelper(hibernateTemplate) } @@ -140,111 +131,6 @@ return fieldIndex == -1 ? null : entry.loadedState[fieldIndex] } - @Override - D lock(D instance) { - hibernateTemplate.lock(instance, LockMode.PESSIMISTIC_WRITE) - } - - @Override - D refresh(D instance) { - hibernateTemplate.refresh(instance) - return instance - } - - @Override - D save(D instance) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", EMPTY_ARRAY) - } - else { - return super.save(instance) - } - } - - D save(D instance, boolean validate) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", [validate] as Object[]) - } - else { - return super.save(instance, validate) - } - } - - @Override - D merge(D instance) { - if (mergeMethod) { - return (D)mergeMethod.invoke(instance, "merge", EMPTY_ARRAY) - } - else { - return super.merge(instance) - } - } - - @Override - D merge(D instance, Map params) { - if (mergeMethod) { - return (D)mergeMethod.invoke(instance, "merge", [params] as Object[]) - } - else { - return super.merge(instance, params) - } - } - - @Override - D save(D instance, Map params) { - if (saveMethod) { - return (D)saveMethod.invoke(instance, "save", [params] as Object[]) - } - else { - return super.save(instance, params) - } - } - - @Override - D attach(D instance) { - hibernateTemplate.lock(instance, LockMode.NONE) - return instance - } - - @Override - void discard(D instance) { - hibernateTemplate.evict instance - } - - @Override - void delete(D instance) { - boolean flush = shouldFlush() - try { - instanceApiHelper.delete instance, flush - } - catch (DataAccessException e) { - handleDataAccessException(hibernateTemplate, e) - } - } - - @Override - void delete(D instance, Map params) { - boolean flush = shouldFlush(params) - try { - instanceApiHelper.delete instance, flush - } - catch (DataAccessException e) { - handleDataAccessException(hibernateTemplate, e) - } - } - - @Override - boolean instanceOf(D instance, Class cls) { - if (instance instanceof HibernateProxy) { - return GrailsHibernateUtil.unwrapProxy(instance) in cls - } - return instance in cls - } - - @Override - boolean isAttached(D instance) { - hibernateTemplate.contains instance - } protected EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) { def entry = session.persistenceContext.getEntry(instance) @@ -259,22 +145,8 @@ entry } - /** - * Session should no longer be flushed after a data access exception occurs (such a constriant violation) - */ - protected void handleDataAccessException(GrailsHibernateTemplate template, DataAccessException e) { - try { - instanceApiHelper.setFlushModeManual() - } - finally { - throw e - } - } - - boolean shouldFlush(Map map = [:]) { - if (map?.containsKey('flush')) { - return Boolean.TRUE == map.flush - } - return config?.autoFlush instanceof Boolean ? config.autoFlush : false + @Override + void setObjectToReadWrite(Object target) { + GrailsHibernateUtil.setObjectToReadWrite(target, sessionFactory) } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy index 8c48df7..02c8ef1 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -15,33 +15,23 @@ */ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass import grails.orm.HibernateCriteriaBuilder +import grails.orm.PagedResultList +import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.orm.hibernate.cfg.CompositeIdentity import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteQueryPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteUpdatePersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ListPersistentMethod -import org.codehaus.groovy.grails.orm.hibernate.metaclass.MergePersistentMethod -import org.grails.datastore.gorm.GormStaticApi +import org.codehaus.groovy.grails.orm.hibernate.query.GrailsHibernateQueryUtils +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.query.api.BuildableCriteria as GrailsCriteria import org.hibernate.Criteria import org.hibernate.LockMode import org.hibernate.Session import org.hibernate.SessionFactory -import org.hibernate.criterion.CriteriaSpecification -import org.hibernate.criterion.Projections -import org.hibernate.criterion.Restrictions import org.springframework.core.convert.ConversionService import org.springframework.orm.hibernate4.SessionFactoryUtils import org.springframework.orm.hibernate4.SessionHolder @@ -55,159 +45,66 @@ * @since 1.0 */ @CompileStatic -class HibernateGormStaticApi<D> extends GormStaticApi<D> { - protected static final EMPTY_ARRAY = [] as Object[] - +class HibernateGormStaticApi<D> extends AbstractHibernateGormStaticApi<D> { protected GrailsHibernateTemplate hibernateTemplate protected SessionFactory sessionFactory protected ConversionService conversionService protected Class identityType - protected ListPersistentMethod listMethod - protected FindAllPersistentMethod findAllMethod - protected FindPersistentMethod findMethod - protected ExecuteQueryPersistentMethod executeQueryMethod - protected ExecuteUpdatePersistentMethod executeUpdateMethod - protected MergePersistentMethod mergeMethod protected ClassLoader classLoader protected GrailsApplication grailsApplication - protected GrailsDomainBinder grailsDomainBinder = new GrailsDomainBinder() - protected int defaultFlushMode + private HibernateGormInstanceApi<D> instanceApi + private int defaultFlushMode HibernateGormStaticApi(Class<D> persistentClass, HibernateDatastore datastore, List<FinderMethod> finders, ClassLoader classLoader, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore, finders, transactionManager) + super(persistentClass, datastore, finders, transactionManager, null) this.classLoader = classLoader sessionFactory = datastore.getSessionFactory() conversionService = datastore.mappingContext.conversionService identityType = persistentEntity.identity?.type - def mappingContext = datastore.mappingContext grailsApplication = datastore.grailsApplication if (grailsApplication) { GrailsDomainClass domainClass = (GrailsDomainClass)grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.name) identityType = domainClass.identifier?.type - mergeMethod = new MergePersistentMethod(sessionFactory, classLoader, grailsApplication, domainClass, datastore) - listMethod = new ListPersistentMethod(grailsApplication, sessionFactory, classLoader, mappingContext.conversionService, datastore.getDefaultFlushMode()) hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication, datastore.getDefaultFlushMode()) } else { hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) hibernateTemplate.setFlushMode(datastore.getDefaultFlushMode()) } - this.defaultFlushMode = datastore.getDefaultFlushMode() - - executeQueryMethod = new ExecuteQueryPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) - executeUpdateMethod = new ExecuteUpdatePersistentMethod(sessionFactory, classLoader, grailsApplication, datastore.getDefaultFlushMode()) - findMethod = new FindPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) - findAllMethod = new FindAllPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService, datastore.getDefaultFlushMode()) + super.hibernateTemplate = hibernateTemplate + + instanceApi = new HibernateGormInstanceApi<>(persistentClass, datastore, classLoader) } -// /** -// * Property missing handling used to relay property access onto target entity for named queries etc. -// * -// * @param property The name of the property -// */ -// @CompileStatic(TypeCheckingMode.SKIP) -// def propertyMissing(String property) { -// if(persistentClass.hasProperty(property)) { -// return this.persistentClass."$property" -// } -// else { -// throw new MissingPropertyException(property, HibernateGormStaticApi) -// } -// } - @Override - D get(Serializable id) { - doGetInstance(id) - } + List<D> list(Map params = Collections.emptyMap()) { + hibernateTemplate.execute { Session session -> + Criteria c = session.createCriteria(persistentEntity.javaClass) + hibernateTemplate.applySettings c - private D doGetInstance(Serializable id) { - if (id || (id instanceof Number)) { - id = convertIdentifier(id) - D result = (D)hibernateTemplate.get((Class)persistentClass, id) - return (D)GrailsHibernateUtil.unwrapIfProxy(result) - } else { - return null - } - } + params = params ? new HashMap(params) : Collections.emptyMap() + setResultTransformer(c) + if(params.containsKey(DynamicFinder.ARGUMENT_MAX)) { - Serializable convertIdentifier(Object id) { - (Serializable)HibernateUtils.convertValueToType(id, identityType, conversionService) - } - - @Override - D read(Serializable id) { - if (id == null) { - return null - } - - hibernateTemplate.execute( { Session session -> - D o = doGetInstance((Serializable)id) - if (o && session.contains(o)) { - session.setReadOnly(o, true) - } - return o - } as GrailsHibernateTemplate.HibernateCallback ) - } - - @Override - D load(Serializable id) { - id = convertIdentifier(id) - if (id != null) { - return (D) hibernateTemplate.load((Class)persistentClass, id) - } - } - - @Override - List<D> getAll() { - (List<D>)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings criteria - criteria.list() + c.setMaxResults(Integer.MAX_VALUE) + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, c, params, datastore.mappingContext.conversionService, true) + return new PagedResultList(hibernateTemplate, c) } - }) - } - - List<D> getAll(List ids) { - getAllInternal(ids) - } - - List<D> getAll(Long... ids) { - getAllInternal(ids as List) - } - - @Override - List<D> getAll(Serializable... ids) { - getAllInternal(ids as List) - } - - private List getAllInternal(List ids) { - if (!ids) return [] - - (List)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - ids = ids.collect { HibernateUtils.convertValueToType((Serializable)it, identityType, conversionService) } - def criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - def identityName = persistentEntity.identity.name - criteria.add(Restrictions.'in'(identityName, ids)) - def results = criteria.list() - def idsMap = [:] - for (object in results) { - idsMap[object[identityName]] = object - } - results.clear() - for (id in ids) { - results << idsMap[id] - } - results + else { + GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, c, params, datastore.mappingContext.conversionService, true) + return c.list() } - }) + } + } + + @CompileDynamic + protected void setResultTransformer(Criteria c) { + c.resultTransformer = Criteria.DISTINCT_ROOT_ENTITY } @Override @@ -215,7 +112,6 @@ def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) builder.grailsApplication = grailsApplication builder.conversionService = conversionService - builder.defaultFlushMode = defaultFlushMode builder } @@ -225,258 +121,55 @@ } @Override - D merge(o) { - (D)mergeMethod.invoke(o, "merge", [] as Object[]) + D merge( D o ) { + instanceApi.merge(o) } @Override - Integer count() { - (Integer)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - def criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.setProjection(Projections.rowCount()) - def num = criteria.uniqueResult() - num == null ? 0 : num + Integer executeUpdate(String query, Map params, Map args) { + def template = hibernateTemplate + SessionFactory sessionFactory = this.sessionFactory + return (Integer) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource( sessionFactory ) + if (sessionHolder && sessionHolder.hasTimeout()) { + q.timeout = sessionHolder.timeToLiveInSeconds } - }) + + populateQueryArguments(q, params) + populateQueryArguments(q, args) + populateQueryWithNamedArguments(q, params) + + return q.executeUpdate() + } } @Override - boolean exists(Serializable id) { - id = convertIdentifier(id) - hibernateTemplate.execute new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - Criteria criteria = session.createCriteria(persistentEntity.javaClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.idEq(id)) - .setProjection(Projections.rowCount()) - .uniqueResult() + Integer executeUpdate(String query, Collection params, Map args) { + def template = hibernateTemplate + SessionFactory sessionFactory = this.sessionFactory + + return (Integer) template.execute { Session session -> + def q = session.createQuery(query) + template.applySettings(q) + def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource( sessionFactory ) + if (sessionHolder && sessionHolder.hasTimeout()) { + q.timeout = sessionHolder.timeToLiveInSeconds } - } - } - @Override - List<D> list(Map params) { - (List<D>)listMethod.invoke(persistentClass, "list", [params] as Object[]) - } - @Override - List<D> list() { - (List<D>)listMethod.invoke(persistentClass, "list", EMPTY_ARRAY) - } - - @Override - List<D> findAll(example, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [example, args] as Object[]) - } - - @Override - D find(example, Map args) { - (D)findMethod.invoke(persistentClass, "find", [example, args] as Object[]) - } - - D first(Map m) { - def entityMapping = grailsDomainBinder.getMapping(persistentEntity.javaClass) - if (entityMapping?.identity instanceof CompositeIdentity) { - throw new UnsupportedOperationException('The first() method is not supported for domain classes that have composite keys.') - } - super.first(m) - } - - D last(Map m) { - def entityMapping = grailsDomainBinder.getMapping(persistentEntity.javaClass) - if (entityMapping?.identity instanceof CompositeIdentity) { - throw new UnsupportedOperationException('The last() method is not supported for domain classes that have composite keys.') - } - super.last(m) - } - - /** - * Finds a single result for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @return A single result or null - * - * @deprecated Use Book.find('..', [foo:'bar], [max:10]) instead - */ - @Deprecated - D find(String query, Map args, Integer max) { - (D)findMethod.invoke(persistentClass, "find", [query, args, max] as Object[]) - } - - /** - * Finds a single result for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @param offset The offset - * @return A single result or null - * - * @deprecated Use Book.find('..', [foo:'bar], [max:10, offset:5]) instead - */ - @Deprecated - D find(String query, Map args, Integer max, Integer offset) { - (D)findMethod.invoke(persistentClass, "find", [query, args, max, offset] as Object[]) - } - - /** - * Finds a single result for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A single result or null - * - * @deprecated Use Book.find('..', [max:10]) instead - */ - @Deprecated - D find(String query, Integer max) { - (D)findMethod.invoke(persistentClass, "find", [query, max] as Object[]) - } - - /** - * Finds a single result for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @param offset The offset to use - * @return A single result or null - * - * @deprecated Use Book.find('..', [max:10, offset:5]) instead - */ - @Deprecated - D find(String query, Integer max, Integer offset) { - (D)findMethod.invoke(persistentClass, "find", [query, max, offset] as Object[]) - } - - /** - * Finds a list of results for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [foo:'bar], [max:10]) instead - */ - @Deprecated - List<D> findAll(String query, Map args, Integer max) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args, max] as Object[]) - } - - /** - * Finds a list of results for the given query and arguments and a maximum results to return value - * - * @param query The query - * @param args The arguments - * @param max The maximum to return - * @param offset The offset - * - * @return A list of results - * - * @deprecated Use findAll('..', [foo:'bar], [max:10, offset:5]) instead - */ - @Deprecated - List<D> findAll(String query, Map args, Integer max, Integer offset) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args, max, offset] as Object[]) - } - - /** - * Finds a list of results for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [max:10]) instead - */ - @Deprecated - List<D> findAll(String query, Integer max) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, max] as Object[]) - } - - /** - * Finds a list of results for the given query and a maximum results to return value - * - * @param query The query - * @param max The maximum to return - * @return A list of results - * - * @deprecated Use findAll('..', [max:10, offset:5]) instead - */ - @Deprecated - List<D> findAll(String query, Integer max, Integer offset) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, max, offset] as Object[]) - } - - @Override - List<D> findAllWhere(Map queryMap, Map args) { - if (!queryMap) return null - - (List<D>)hibernateTemplate.execute( { Session session -> - Map<String, Object> processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) - - List<String> nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) + params.eachWithIndex { val, int i -> + if (val instanceof CharSequence) { + q.setParameter i, val.toString() } - criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY) - criteria.list() - } as GrailsHibernateTemplate.HibernateCallback) - } - - @Override - D findWhere(Map queryMap, Map args) { - if (!queryMap) return null - - (D)hibernateTemplate.execute( { Session session -> - Map<String, Object> processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) - List<String> nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) + else { + q.setParameter i, val } - criteria.setMaxResults(1) - GrailsHibernateUtil.unwrapIfProxy(criteria.uniqueResult()) - } as GrailsHibernateTemplate.HibernateCallback) - } - - private Map filterQueryArgumentMap(Map query) { - def queryArgs = [:] - for (entry in query.entrySet()) { - if (entry.value instanceof CharSequence) { - queryArgs[entry.key] = entry.value.toString() } - else { - queryArgs[entry.key] = entry.value - } + populateQueryArguments(q, args) + return q.executeUpdate() } - return queryArgs - } - - private List<String> removeNullNames(Map query) { - List<String> nullNames = [] - Set<String> allNames = new HashSet(query.keySet()) - for (String name in allNames) { - def value = query[name] - if (value == null) { - query.remove name - nullNames << name - } - } - nullNames } @Override @@ -535,116 +228,5 @@ } } - @Override - List<D> executeQuery(String query) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query] as Object[]) - } - List<D> executeQuery(String query, arg) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, arg] as Object[]) - } - - @Override - List<D> executeQuery(String query, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, args] as Object[]) - } - - @Override - List<D> executeQuery(String query, Map params, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - List<D> executeQuery(String query, Collection params) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params] as Object[]) - } - - @Override - List<D> executeQuery(String query, Collection params, Map args) { - (List<D>)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - Integer executeUpdate(String query) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query] as Object[]) - } - - @Override - Integer executeUpdate(String query, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, args] as Object[]) - } - - @Override - Integer executeUpdate(String query, Map params, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params, args] as Object[]) - } - - @Override - Integer executeUpdate(String query, Collection params) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params] as Object[]) - } - - @Override - Integer executeUpdate(String query, Collection params, Map args) { - (Integer)executeUpdateMethod.invoke(persistentClass, "executeUpdate", [query, params, args] as Object[]) - } - - @Override - D find(String query) { - (D)findMethod.invoke(persistentClass, "find", [query] as Object[]) - } - - D find(String query, Object[] params) { - (D)findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, args] as Object[]) - } - - @Override - D find(String query, Map params, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - Object find(String query, Collection params) { - findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Collection params, Map args) { - (D)findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - List<D> findAll(String query) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query] as Object[]) - } - - @Override - List<D> findAll(String query, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, args] as Object[]) - } - - @Override - List<D> findAll(String query, Map params, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - List<D> findAll(String query, Collection params) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params] as Object[]) - } - - @Override - List<D> findAll(String query, Collection params, Map args) { - (List<D>)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - D create() { - return (D)super.create() - } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy index 4fcb082..6881ddf 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy
@@ -17,22 +17,10 @@ import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod - @CompileStatic class HibernateGormValidationApi<D> extends AbstractHibernateGormValidationApi<D> { - ValidatePersistentMethod validateMethod - HibernateGormValidationApi(Class<D> persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - def grailsApplication = datastore.grailsApplication - if (grailsApplication) { - def validator = mappingContext.getEntityValidator(mappingContext.getPersistentEntity(persistentClass.name)) - validateMethod = new ValidatePersistentMethod(datastore.getSessionFactory(), - classLoader, grailsApplication, validator, datastore) - } } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java index ead80b9..22228b4 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java
@@ -21,10 +21,10 @@ import javax.persistence.FlushModeType; -import org.codehaus.groovy.grails.commons.GrailsApplication; +import grails.core.GrailsApplication; +import grails.core.support.proxy.ProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.query.HibernateQuery; -import org.codehaus.groovy.grails.support.proxy.ProxyHandler; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java index c36c272..1da399a 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java
@@ -14,20 +14,26 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.GrailsApplication; +import grails.core.GrailsClass; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import groovy.lang.Closure; import groovy.util.Eval; import java.util.HashSet; +import java.util.Properties; import java.util.Set; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwarePojoEntityTuplizer; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Mappings; +import org.hibernate.cfg.Settings; +import org.hibernate.service.ServiceRegistry; /** * Creates runtime configuration mapping for the Grails domain classes @@ -81,6 +87,19 @@ dataSourceName = name; } + @Override + public Settings buildSettings(ServiceRegistry serviceRegistry) { + Settings settings = super.buildSettings(serviceRegistry); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + + @Override + public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) throws HibernateException { + Settings settings = super.buildSettings(props, serviceRegistry); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } /** * Overrides the default behaviour to including binding of Grails domain classes. */
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java index f25d6fb..e387a6c 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java
@@ -15,16 +15,16 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; import org.codehaus.groovy.grails.orm.hibernate.EventListenerIntegrator; import org.codehaus.groovy.grails.orm.hibernate.GrailsSessionContext; import org.codehaus.groovy.grails.orm.hibernate.HibernateEventListeners; -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.SessionFactory; -import org.hibernate.SessionFactoryObserver; +import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwarePojoEntityTuplizer; +import org.grails.core.artefact.AnnotationDomainClassArtefactHandler; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.hibernate.*; import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; @@ -56,6 +56,7 @@ import javax.persistence.Entity; import javax.persistence.MappedSuperclass; import java.io.IOException; +import java.lang.InstantiationException; import java.util.*; /** @@ -100,6 +101,9 @@ if (shouldMapWithGorm(domainClass)) { domainClasses.add(domainClass); } + else { + addAnnotatedClass(domainClass.getClazz()); + } return this; } @@ -332,6 +336,20 @@ } @Override + public Settings buildSettings(ServiceRegistry serviceRegistry) { + Settings settings = super.buildSettings(serviceRegistry); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + + @Override + public Settings buildSettings(Properties props, ServiceRegistry serviceRegistry) throws HibernateException { + Settings settings = super.buildSettings(props, serviceRegistry); + settings.getEntityTuplizerFactory().registerDefaultTuplizerClass(EntityMode.POJO, GroovyAwarePojoEntityTuplizer.class); + return settings; + } + + @Override public SessionFactory buildSessionFactory() throws HibernateException { // set the class loader to load Groovy classes
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 0e14799..75f6d15 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java
@@ -17,13 +17,13 @@ import java.util.Arrays; import java.util.List; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.validation.ConstrainedProperty; +import grails.validation.Constraint; import org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareJoinedSubclassEntityPersister; import org.codehaus.groovy.grails.orm.hibernate.persister.entity.GroovyAwareSingleTableEntityPersister; import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -import org.codehaus.groovy.grails.validation.Constraint; import org.hibernate.mapping.Column; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.Table;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java index 318d910..0bc0d5d 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java
@@ -15,19 +15,25 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg; +import grails.core.GrailsApplication; +import grails.core.GrailsClass; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import grails.util.CollectionUtils; +import grails.util.GrailsClassUtils; import grails.util.Holders; import groovy.lang.GroovyObject; import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateDomainClass; import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.query.HibernateQueryConstants; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.grails.core.DefaultGrailsDomainClass; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.hibernate.*; import org.hibernate.criterion.Order; import org.hibernate.engine.spi.EntityEntry;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy index f22d04e..902440a 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy
@@ -16,15 +16,15 @@ package org.codehaus.groovy.grails.orm.hibernate.cfg import grails.artefact.Enhanced +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.util.GrailsClassUtils +import grails.util.GrailsMetaClassUtils import grails.util.GrailsNameUtils import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsClassUtils -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore import org.codehaus.groovy.grails.orm.hibernate.HibernateGormEnhancer @@ -32,8 +32,9 @@ import org.codehaus.groovy.grails.orm.hibernate.HibernateGormStaticApi import org.codehaus.groovy.grails.orm.hibernate.HibernateGormValidationApi import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor +import org.codehaus.groovy.grails.orm.hibernate.support.HibernateRuntimeUtils import org.codehaus.groovy.runtime.InvokerHelper -import org.codehaus.groovy.runtime.StringGroovyMethods +import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity @@ -186,13 +187,14 @@ // http://jira.codehaus.org/browse/GROOVY-6138 prevents using CompileStatic for this method @CompileStatic(TypeCheckingMode.SKIP) static void enhanceProxyClass(Class proxyClass) { - MetaMethod grailsEnhancedMetaMethod = proxyClass.metaClass.getStaticMetaMethod("grailsEnhanced", (Class[])null) + + MetaClass mc = GrailsMetaClassUtils.getExpandoMetaClass(proxyClass) + MetaMethod grailsEnhancedMetaMethod = mc.getStaticMetaMethod("grailsEnhanced", (Class[])null) if (grailsEnhancedMetaMethod != null && grailsEnhancedMetaMethod.invoke(proxyClass, null) == proxyClass) { return } - MetaClass mc = (MetaClass)InvokerHelper.getMetaClass(proxyClass) - MetaClass superMc = InvokerHelper.getMetaClass(proxyClass.getSuperclass()) + MetaClass superMc = GrailsMetaClassUtils.getExpandoMetaClass(proxyClass.getSuperclass()) // hasProperty registerMetaMethod(mc, 'hasProperty', { String name -> @@ -332,38 +334,6 @@ } static Object convertValueToType(Object passedValue, Class targetType, ConversionService conversionService) { - // workaround for GROOVY-6127, do not assign directly in parameters before it's fixed - Object value = passedValue - if(targetType != null && value != null && !(value in targetType)) { - if (value instanceof CharSequence) { - value = value.toString() - if(value in targetType) { - return value - } - } - try { - if (value instanceof Number && (targetType==Long || targetType==Integer)) { - if(targetType == Long) { - value = ((Number)value).toLong() - } else { - value = ((Number)value).toInteger() - } - } else if (value instanceof String && targetType in Number) { - String strValue = value.trim() - if(targetType == Long) { - value = Long.parseLong(strValue) - } else if (targetType == Integer) { - value = Integer.parseInt(strValue) - } else { - value = StringGroovyMethods.asType(strValue, targetType) - } - } else { - value = conversionService.convert(value, targetType) - } - } catch (e) { - // ignore - } - } - return value + HibernateRuntimeUtils.convertValueToType(passedValue, targetType, conversionService) } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java deleted file mode 100644 index ede2b7a..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java +++ /dev/null
@@ -1,549 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.RlikeExpression; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; -import groovy.lang.Range; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.*; -import org.hibernate.Criteria; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.CriteriaQuery; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; -import org.hibernate.engine.spi.TypedValue; -import org.springframework.beans.TypeMismatchException; -import org.springframework.core.convert.ConversionService; -import org.springframework.util.Assert; - -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public abstract class AbstractClausedStaticPersistentMethod extends AbstractStaticPersistentMethod { - - protected static final Log LOG = LogFactory.getLog(AbstractClausedStaticPersistentMethod.class); - - /** - * @author Graeme Rocher - */ - protected abstract static class GrailsMethodExpression { - protected static final String LESS_THAN = "LessThan"; - protected static final String LESS_THAN_OR_EQUAL = "LessThanEquals"; - protected static final String GREATER_THAN = "GreaterThan"; - protected static final String GREATER_THAN_OR_EQUAL = "GreaterThanEquals"; - protected static final String LIKE = "Like"; - protected static final String ILIKE = "Ilike"; - protected static final String RLIKE = "Rlike"; - protected static final String BETWEEN = "Between"; - protected static final String IN_LIST= "InList"; - protected static final String IS_NOT_NULL = "IsNotNull"; - protected static final String IS_NULL = "IsNull"; - protected static final String NOT = "Not"; - protected static final String EQUAL = "Equal"; - protected static final String NOT_EQUAL = "NotEqual"; - protected static final String IN_RANGE = "InRange"; - - protected String propertyName; - protected Object[] arguments; - protected int argumentsRequired; - protected boolean negation; - protected String type; - protected Class<?> targetClass; - private GrailsApplication application; - protected final ConversionService conversionService; - - /** - * Used as an indication that an expression will return no results, so stop processing and return nothing. - */ - static final Criterion FORCE_NO_RESULTS = new Criterion() { - private static final long serialVersionUID = 1L; - public TypedValue[] getTypedValues(Criteria c, CriteriaQuery q) { return null; } - public String toSqlString(Criteria c, CriteriaQuery q) { return null; } - }; - - GrailsMethodExpression(GrailsApplication application, Class<?> targetClass, - String propertyName, String type, int argumentsRequired, boolean negation, ConversionService conversionService) { - this.application = application; - this.targetClass = targetClass; - this.propertyName = propertyName; - this.type = type; - this.argumentsRequired = argumentsRequired; - this.negation = negation; - this.conversionService = conversionService; - } - - GrailsMethodExpression(GrailsApplication application, Class<?> targetClass, - String queryParameter, String type, int argumentsRequired, ConversionService conversionService) { - this(application, targetClass, calcPropertyName(queryParameter, type), type, - argumentsRequired, isNegation(queryParameter, type), conversionService); - } - - public String getPropertyName() { - return propertyName; - } - - public Object[] getArguments() { - Object[] copy = new Object[arguments.length]; - System.arraycopy(arguments, 0, copy, 0, arguments.length); - return copy; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("[GrailsMethodExpression] "); - buf.append(propertyName) - .append(" ") - .append(type) - .append(" "); - - for (int i = 0; i < arguments.length; i++) { - buf.append(arguments[i]); - if (i != arguments.length) { - buf.append(" and "); - } - } - return buf.toString(); - } - - @SuppressWarnings("unchecked") - protected void setArguments(Object[] args) throws IllegalArgumentException { - if (args.length != argumentsRequired) { - throw new IllegalArgumentException("Method expression '" + type + "' requires " + - argumentsRequired + " arguments"); - } - - GrailsDomainClass dc = (GrailsDomainClass)application.getArtefact( - DomainClassArtefactHandler.TYPE, targetClass.getName()); - GrailsDomainClassProperty prop = dc.getPropertyByName(propertyName); - - if (prop == null) { - throw new IllegalArgumentException("Property " + propertyName + - " doesn't exist for method expression '"+ type + "'"); - } - - for (int i = 0; i < args.length; i++) { - Object currentArg = args[i]; - if (currentArg == null) continue; - // convert GStrings to strings - if (prop.getType() == String.class && (currentArg instanceof CharSequence)) { - args[i] = currentArg.toString(); - } - else if (!prop.getType().isAssignableFrom(currentArg.getClass()) && !(GrailsClassUtils.isMatchBetweenPrimativeAndWrapperTypes(prop.getType(), currentArg.getClass()))) { - try { - if (type.equals(IN_LIST)) { - if(currentArg instanceof Collection) { - currentArg = convertArgumentList(prop, (Collection)currentArg); - } - args[i] = conversionService.convert(currentArg, Collection.class); - } - else { - args[i] = conversionService.convert(currentArg, prop.getType()); - } - } - catch (TypeMismatchException tme) { - // if we cannot perform direct conversion and argument is subclass of Number - // we can try to convert it through its String representation - if (Number.class.isAssignableFrom(currentArg.getClass())) { - try { - args[i] = conversionService.convert(currentArg.toString(), prop.getType()); - } - catch(TypeMismatchException tme1) { - throw new IllegalArgumentException("Cannot convert value " + currentArg + " of property '"+propertyName+"' to required type " + prop.getType() + ": " + tme1.getMessage()); - } - } - else { - throw new IllegalArgumentException("Cannot convert value " + currentArg + " of property '"+propertyName+"' to required type " + prop.getType()); - } - } - } - else if(type.equals(IN_LIST) && (currentArg instanceof Collection)) { - currentArg = convertArgumentList(prop, (Collection) currentArg); - } - } - - arguments = args; - } - - protected List convertArgumentList(GrailsDomainClassProperty prop, Collection argList) { - List convertedList = new ArrayList(argList.size()); - for (Object item : argList) { - if(item instanceof CharSequence) { - item = item.toString(); - } - convertedList.add(conversionService.convert(item, prop.getType())); - } - return convertedList; - } - - abstract Criterion createCriterion(); - - protected Criterion getCriterion() { - Assert.notNull(arguments, "Parameters array must be set before retrieving Criterion"); - return negation ? Restrictions.not(createCriterion()) : createCriterion(); - } - - protected static GrailsMethodExpression create(final GrailsApplication application, - Class<?> clazz, String queryParameter, ConversionService conversionService) { - - if (queryParameter.endsWith(LESS_THAN_OR_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LESS_THAN_OR_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.le(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(LESS_THAN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LESS_THAN, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.lt(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(GREATER_THAN_OR_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, GREATER_THAN_OR_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.ge(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(GREATER_THAN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, GREATER_THAN, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.gt(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(LIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, LIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.like(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(ILIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, ILIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.ilike(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(RLIKE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, RLIKE, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return new RlikeExpression(propertyName, arguments[0]); - } - }; - } - - if (queryParameter.endsWith(IS_NOT_NULL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IS_NOT_NULL, 0, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.isNotNull(propertyName); - } - }; - } - - if (queryParameter.endsWith(IS_NULL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IS_NULL, 0, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.isNull(propertyName); - } - }; - } - - if (queryParameter.endsWith(BETWEEN)) { - return new GrailsMethodExpression(application, clazz, queryParameter, BETWEEN, 2, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.between(propertyName,arguments[0], arguments[1]); - } - }; - } - - if (queryParameter.endsWith(IN_LIST)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IN_LIST, 1, conversionService) { - @SuppressWarnings("rawtypes") - @Override - Criterion createCriterion() { - Collection collection = (Collection)arguments[0]; - if (collection == null || collection.isEmpty()) { - return FORCE_NO_RESULTS; - } - return Restrictions.in(propertyName, collection); - } - }; - } - - if (queryParameter.endsWith(NOT_EQUAL)) { - return new GrailsMethodExpression(application, clazz, queryParameter, NOT_EQUAL, 1, conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNotNull(propertyName); - return Restrictions.ne(propertyName,arguments[0]); - } - }; - } - - if (queryParameter.endsWith(IN_RANGE)) { - return new GrailsMethodExpression(application, clazz, queryParameter, IN_RANGE, 1, conversionService) { - @Override - Criterion createCriterion() { - return Restrictions.between(propertyName, arguments[0], arguments[1]); - } - @Override - protected void setArguments(Object[] args) throws IllegalArgumentException { - if (args != null && args.length > 0 && args[0] instanceof Range) { - Range<?> range = (Range<?>) args[0]; - args = new Object[] { range.getFrom(), range.getTo() }; - argumentsRequired = 2; - } - super.setArguments(args); - } - }; - } - - return new GrailsMethodExpression(application, clazz, - calcPropertyName(queryParameter, null), - EQUAL, 1, isNegation(queryParameter, EQUAL), conversionService) { - @Override - Criterion createCriterion() { - if (arguments[0] == null) return Restrictions.isNull(propertyName); - return Restrictions.eq(propertyName,arguments[0]); - } - }; - } - - private static boolean isNegation(String queryParameter, String clause) { - String propName; - if (clause != null && !clause.equals(EQUAL)) { - int i = queryParameter.indexOf(clause); - propName = queryParameter.substring(0,i); - } - else { - propName = queryParameter; - } - return propName.endsWith(NOT); - } - - private static String calcPropertyName(String queryParameter, String clause) { - String propName; - if (clause != null && !clause.equals(EQUAL)) { - int i = queryParameter.indexOf(clause); - propName = queryParameter.substring(0,i); - } - else { - propName = queryParameter; - } - if (propName.endsWith(NOT)) { - int i = propName.lastIndexOf(NOT); - propName = propName.substring(0, i); - } - return propName.substring(0,1).toLowerCase(Locale.ENGLISH) + propName.substring(1); - } - } - - private final String[] operators; - private final Pattern[] operatorPatterns; - protected final ConversionService conversionService; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - * @param pattern - * @param operators - */ - public AbstractClausedStaticPersistentMethod(GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader, Pattern pattern, String[] operators, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, pattern, application, defaultFlushMode); - this.operators = operators; - operatorPatterns = new Pattern[operators.length]; - for (int i = 0; i < operators.length; i++) { - operatorPatterns[i] = Pattern.compile("(\\w+)("+operators[i]+")(\\p{Upper})(\\w+)"); - } - this.conversionService = conversionService; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod#doInvokeInternal(java.lang.Class, java.lang.String, java.lang.Object[]) - */ - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, - Closure additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz, methodName, null, additionalCriteria, arguments); - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz, methodName, additionalCriteria,null, arguments); - } - - protected Object doInvokeInternal(Class<?> clazz, String methodName, DetachedCriteria<?> detachedCriteria, Closure<?> additionalCriteria, Object[] arguments) { - List<GrailsMethodExpression> expressions = new ArrayList<GrailsMethodExpression>(); - if (arguments == null) arguments = new Object[0]; - Matcher match = super.getPattern().matcher(methodName); - // find match - match.find(); - - String[] queryParameters; - int totalRequiredArguments = 0; - // get the sequence clauses - final String querySequence; - int groupCount = match.groupCount(); - if (groupCount == 6) { - String booleanProperty = match.group(3); - if (booleanProperty == null) { - booleanProperty = match.group(6); - querySequence = null; - } - else { - querySequence = match.group(5); - } - Boolean arg = Boolean.TRUE; - if (booleanProperty.matches("Not[A-Z].*")) { - booleanProperty = booleanProperty.substring(3); - arg = Boolean.FALSE; - } - GrailsMethodExpression booleanExpression = GrailsMethodExpression.create( - application, clazz, booleanProperty, conversionService); - booleanExpression.setArguments(new Object[]{arg}); - expressions.add(booleanExpression); - } - else { - querySequence = match.group(2); - } - // if it contains operator and split - boolean containsOperator = false; - String operatorInUse = null; - - if (querySequence != null) { - for (int i = 0; i < operators.length; i++) { - Matcher currentMatcher = operatorPatterns[i].matcher(querySequence); - if (currentMatcher.find()) { - containsOperator = true; - operatorInUse = operators[i]; - - queryParameters = querySequence.split(operatorInUse); - - // loop through query parameters and create expressions - // calculating the number of arguments required for the expression - int argumentCursor = 0; - for (String queryParameter : queryParameters) { - GrailsMethodExpression currentExpression = GrailsMethodExpression.create( - application, clazz, queryParameter, conversionService); - totalRequiredArguments += currentExpression.argumentsRequired; - // populate the arguments into the GrailsExpression from the argument list - Object[] currentArguments = new Object[currentExpression.argumentsRequired]; - if ((argumentCursor + currentExpression.argumentsRequired) > arguments.length) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - for (int k = 0; k < currentExpression.argumentsRequired; k++, argumentCursor++) { - currentArguments[k] = arguments[argumentCursor]; - } - try { - currentExpression.setArguments(currentArguments); - } - catch (IllegalArgumentException iae) { - LOG.debug(iae.getMessage(), iae); - throw new MissingMethodException(methodName, clazz, arguments); - } - // add to list of expressions - expressions.add(currentExpression); - } - break; - } - } - } - - // otherwise there is only one expression - if (!containsOperator && querySequence != null) { - GrailsMethodExpression solo = GrailsMethodExpression.create(application, clazz, querySequence, conversionService); - - if (solo.argumentsRequired > arguments.length) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - totalRequiredArguments += solo.argumentsRequired; - Object[] soloArgs = new Object[solo.argumentsRequired]; - - System.arraycopy(arguments, 0, soloArgs, 0, solo.argumentsRequired); - try { - solo.setArguments(soloArgs); - } - catch (IllegalArgumentException iae) { - LOG.debug(iae.getMessage(), iae); - throw new MissingMethodException(methodName,clazz,arguments); - } - expressions.add(solo); - } - - // if the total of all the arguments necessary does not equal the number of arguments throw exception - if (totalRequiredArguments > arguments.length) { - throw new MissingMethodException(methodName,clazz,arguments); - } - - // calculate the remaining arguments - Object[] remainingArguments = new Object[arguments.length - totalRequiredArguments]; - if (remainingArguments.length > 0) { - for (int i = 0, j = totalRequiredArguments; i < remainingArguments.length; i++,j++) { - remainingArguments[i] = arguments[j]; - } - } - - if (LOG.isTraceEnabled()) { - LOG.trace("Calculated expressions: " + expressions); - } - - return doInvokeInternalWithExpressions(clazz, methodName, remainingArguments, expressions, operatorInUse, detachedCriteria, additionalCriteria); - } - - @SuppressWarnings("rawtypes") - protected abstract Object doInvokeInternalWithExpressions(Class clazz, String methodName, Object[] arguments, List expressions, String operatorInUse, DetachedCriteria detachedCriteria, Closure additionalCriteria); -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java deleted file mode 100644 index 140c537..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractDynamicPersistentMethod.java +++ /dev/null
@@ -1,122 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.ValidationErrors; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.metaclass.AbstractDynamicMethodInvocation; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.SessionFactory; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; -import org.springframework.validation.FieldError; - -/** - * @author Steven Devijver - */ -public abstract class AbstractDynamicPersistentMethod extends AbstractDynamicMethodInvocation { - - public static final String ERRORS_PROPERTY = "errors"; - - private ClassLoader classLoader; - private GrailsHibernateTemplate hibernateTemplate; - private SessionFactory sessionFactory; - GrailsApplication application; - int defaultFlushMode; - - public AbstractDynamicPersistentMethod(Pattern pattern, SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, int defaultFlushMode) { - super(pattern); - Assert.notNull(sessionFactory, "Session factory is required!"); - this.classLoader = classLoader; - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.application = application; - this.sessionFactory = sessionFactory; - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, application, defaultFlushMode); - } - - protected SessionFactory getSessionFactory() { - return sessionFactory; - } - - protected GrailsHibernateTemplate getHibernateTemplate() { - return hibernateTemplate; - } - - @Override - public Object invoke(Object target, String methodName, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(target, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - protected abstract Object doInvokeInternal(Object target, Object[] arguments); - - /** - * This method will set the target object to read-only if it is contained with the Hibernate session, - * Preventing Hibernate dirty-checking from persisting the instance - * - * @param target The target object - */ - protected void setObjectToReadOnly(final Object target) { - GrailsHibernateUtil.setObjectToReadyOnly(target, sessionFactory); - } - - protected void setObjectToReadWrite(final Object target) { - GrailsHibernateUtil.setObjectToReadWrite(target, sessionFactory); - } - - /** - * Initializes the Errors property on target. The target will be assigned a new - * Errors property. If the target contains any binding errors, those binding - * errors will be copied in to the new Errors property. - * - * @param target object to initialize - * @return the new Errors object - */ - protected Errors setupErrorsProperty(Object target) { - MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - - ValidationErrors errors = new ValidationErrors(target); - - Errors originalErrors = (Errors) mc.getProperty(target, ERRORS_PROPERTY); - for (Object o : originalErrors.getFieldErrors()) { - FieldError fe = (FieldError)o; - if (fe.isBindingFailure()) { - errors.addError(new FieldError(fe.getObjectName(), - fe.getField(), - fe.getRejectedValue(), - fe.isBindingFailure(), - fe.getCodes(), - fe.getArguments(), - fe.getDefaultMessage())); - } - } - - mc.setProperty(target, ERRORS_PROPERTY, errors); - return errors; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java deleted file mode 100644 index 3721f23..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethod.java +++ /dev/null
@@ -1,180 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.NonUniqueResultException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Restrictions; -import org.hibernate.internal.CriteriaImpl; - -public abstract class AbstractFindByPersistentMethod extends AbstractClausedStaticPersistentMethod { - public static final String OPERATOR_OR = "Or"; - public static final String OPERATOR_AND = "And"; - public static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - private static final Map<String, Boolean> useLimitCache = new ConcurrentHashMap<String, Boolean>(); - - public AbstractFindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, - SessionFactory sessionFactory, ClassLoader classLoader, - Pattern pattern, String[] operators) { - super(application, sessionFactory, classLoader, pattern, operators, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternalWithExpressions(final Class clazz, String methodName, final Object[] arguments, final List expressions, String operatorInUse, final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - final String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = buildCriteria(session, detachedCriteria, additionalCriteria, clazz, arguments, operator, expressions); - - boolean useLimit = establishWhetherToUseLimit(clazz); - return getResult(crit, useLimit); - } - }); - } - - private boolean establishWhetherToUseLimit(Class<?> clazz) { - boolean useLimit = true; - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, clazz.getName()); - if (domainClass != null) { - Boolean aBoolean = useLimitCache.get(domainClass.getName()); - if (aBoolean != null) { - useLimit = aBoolean; - } - else { - - for (GrailsDomainClassProperty property : domainClass.getPersistentProperties()) { - if ((property.isOneToMany()||property.isManyToMany()) && property.getFetchMode() == GrailsDomainClassProperty.FETCH_EAGER) { - useLimit = false; - useLimitCache.put(domainClass.getName(), useLimit); - break; - } - } - } - } - return useLimit; - } - - protected Object getResult(Criteria crit) { - CriteriaImpl impl = (CriteriaImpl) crit; - String entityOrClassName = impl.getEntityOrClassName(); - GrailsClass domainClass = application.getArtefact(DomainClassArtefactHandler.TYPE, entityOrClassName); - boolean useLimit = establishWhetherToUseLimit(domainClass.getClazz()); - - return getResult(crit, useLimit); - } - - protected Object getResult(Criteria crit, boolean useLimit) { - if (useLimit) { - final List<?> list = crit.list(); - if (!list.isEmpty()) { - return GrailsHibernateUtil.unwrapIfProxy(list.get(0)); - } - } - else { - try { - return crit.uniqueResult(); - } catch (NonUniqueResultException e) { - return null; - } - } - return null; - } - - protected Criteria buildCriteria(Session session, DetachedCriteria<?> detachedCriteria, - Closure<?> additionalCriteria, Class<?> clazz, Object[] arguments, - String operator, List<?> expressions) { - Criteria crit = getCriteria(datastore, application, session, detachedCriteria, additionalCriteria, clazz); - - boolean useLimit = establishWhetherToUseLimit(clazz); - - if (arguments.length > 0) { - if (arguments[0] instanceof Map<?, ?>) { - Map<?, ?> argMap = (Map<?, ?>)arguments[0]; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argMap, conversionService); - if (!argMap.containsKey(GrailsHibernateUtil.ARGUMENT_FETCH)) { - if (useLimit) { - crit.setMaxResults(1); - } - } - } - else { - if (useLimit) { - crit.setMaxResults(1); - } - } - } - else { - if (useLimit) { - crit.setMaxResults(1); - } - } - - if (operator.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - GrailsMethodExpression expression = (GrailsMethodExpression) expressions.remove(0); - crit.add(expression.getCriterion()); - } - Disjunction dis = Restrictions.disjunction(); - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - crit.add(current.getCriterion()); - } - } - return crit; - } - - /** - * Indicates if the first expression in the query is a required boolean property and as such should - * be ANDed to the other expressions, not ORed. - * - * @return true if the first expression is a required boolean property, false otherwise - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByBooleanPropertyPersistentMethod - */ - protected boolean firstExpressionIsRequiredBoolean() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java deleted file mode 100644 index d342d16..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractSavePersistentMethod.java +++ /dev/null
@@ -1,377 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.DeferredBindingActions; -import grails.validation.ValidationException; -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint; -import org.codehaus.groovy.grails.validation.CascadingValidator; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.InvalidPropertyException; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * Abstract class for different implementations that perform saving to implement. - * - * @author Graeme Rocher - * @since 0.3 - */ -public abstract class AbstractSavePersistentMethod extends AbstractDynamicPersistentMethod { - - private HibernateDatastore datastore; - private static final String ARGUMENT_VALIDATE = "validate"; - private static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; - private static final String ARGUMENT_FLUSH = "flush"; - private static final String ARGUMENT_INSERT = "insert"; - private static final String ARGUMENT_FAIL_ON_ERROR = "failOnError"; - private static final String FAIL_ON_ERROR_CONFIG_PROPERTY = "grails.gorm.failOnError"; - private static final String AUTO_FLUSH_CONFIG_PROPERTY = "grails.gorm.autoFlush"; - - /** - * When a domain instance is saved without validation, we put it - * into this thread local variable. Any code that needs to know - * whether the domain instance should be validated can just check - * the value. Note that this only works because the session is - * flushed when a domain instance is saved without validation. - */ - private static ThreadLocal<Set<Integer>> disableAutoValidationFor = new ThreadLocal<Set<Integer>>(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - disableAutoValidationFor.remove(); - } - }); - } - - private static Set<Integer> getDisableAutoValidationFor() { - Set<Integer> identifiers = disableAutoValidationFor.get(); - if (identifiers == null) - disableAutoValidationFor.set(identifiers = new HashSet<Integer>()); - return identifiers; - } - - public static boolean isAutoValidationDisabled(Object obj) { - Set<Integer> identifiers = getDisableAutoValidationFor(); - return obj != null && identifiers.contains(System.identityHashCode(obj)); - } - - public static void clearDisabledValidations(Object obj) { - getDisableAutoValidationFor().remove(System.identityHashCode(obj)); - } - - public static void clearDisabledValidations() { - getDisableAutoValidationFor().clear(); - } - - public AbstractSavePersistentMethod(Pattern pattern, SessionFactory sessionFactory, - ClassLoader classLoader, GrailsApplication application, - GrailsDomainClass domainClass, HibernateDatastore datastore) { - super(pattern, sessionFactory, classLoader, application, datastore.getDefaultFlushMode()); - - this.datastore = datastore; - } - - public AbstractSavePersistentMethod(Pattern pattern, SessionFactory sessionFactory, - ClassLoader classLoader, GrailsApplication application, HibernateDatastore datastore) { - this(pattern, sessionFactory, classLoader, application, null, datastore); - } - - @SuppressWarnings("rawtypes") - private boolean shouldFail(GrailsApplication grailsApplication, GrailsDomainClass domainClass) { - boolean shouldFail = false; - final Map config = grailsApplication.getFlatConfig(); - if (config.containsKey(FAIL_ON_ERROR_CONFIG_PROPERTY)) { - Object configProperty = config.get(FAIL_ON_ERROR_CONFIG_PROPERTY); - if (configProperty instanceof Boolean) { - shouldFail = Boolean.TRUE == configProperty; - } - else if (configProperty instanceof List) { - if (domainClass != null) { - final Class theClass = domainClass.getClazz(); - List packageList = (List) configProperty; - shouldFail = GrailsClassUtils.isClassBelowPackage(theClass, packageList); - } - } - } - return shouldFail; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod#doInvokeInternal(java.lang.Object, java.lang.Object[]) - */ - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(final Object target, Object[] arguments) { - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - target.getClass().getName()); - - DeferredBindingActions.runActions(); - boolean shouldFlush = shouldFlush(arguments); - boolean shouldValidate = shouldValidate(arguments, domainClass); - if (shouldValidate) { - Validator validator = domainClass.getValidator(); - - if (domainClass instanceof DefaultGrailsDomainClass) { - GrailsHibernateUtil.autoAssociateBidirectionalOneToOnes((DefaultGrailsDomainClass) domainClass, target); - } - Errors errors = setupErrorsProperty(target); - - if (validator != null) { - datastore.getApplicationContext().publishEvent(new ValidationEvent(datastore, target)); - - boolean deepValidate = true; - Map argsMap = null; - if (arguments.length > 0 && arguments[0] instanceof Map) { - argsMap = (Map) arguments[0]; - } - if (argsMap != null && argsMap.containsKey(ARGUMENT_DEEP_VALIDATE)) { - deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap); - } - - AbstractPersistentConstraint.sessionFactory.set(datastore.getSessionFactory()); - try { - if (deepValidate && (validator instanceof CascadingValidator)) { - ((CascadingValidator)validator).validate(target, errors, deepValidate); - } - else { - validator.validate(target,errors); - } - } - finally { - AbstractPersistentConstraint.sessionFactory.remove(); - } - - if (errors.hasErrors()) { - handleValidationError(domainClass,target,errors); - boolean shouldFail = shouldFail(application, domainClass); - if (argsMap != null && argsMap.containsKey(ARGUMENT_FAIL_ON_ERROR)) { - shouldFail = GrailsClassUtils.getBooleanFromMap(ARGUMENT_FAIL_ON_ERROR, argsMap); - } - if (shouldFail) { - throw new ValidationException("Validation Error(s) occurred during save()", errors); - } - return null; - } - - setObjectToReadWrite(target); - } - } - - // this piece of code will retrieve a persistent instant - // of a domain class property is only the id is set thus - // relieving this burden off the developer - if (domainClass != null) { - autoRetrieveAssocations(domainClass, target); - } - - if (!shouldValidate) { - Set<Integer> identifiers = getDisableAutoValidationFor(); - identifiers.add(System.identityHashCode(target)); - } - - if (shouldInsert(arguments)) { - return performInsert(target, shouldFlush); - } - - return performSave(target, shouldFlush); - } - - @SuppressWarnings("rawtypes") - private boolean shouldInsert(Object[] arguments) { - return arguments.length > 0 && arguments[0] instanceof Map && - GrailsClassUtils.getBooleanFromMap(ARGUMENT_INSERT, (Map) arguments[0]); - } - - @SuppressWarnings("rawtypes") - private boolean shouldFlush(Object[] arguments) { - final boolean shouldFlush; - if (arguments.length > 0 && arguments[0] instanceof Boolean) { - shouldFlush = (Boolean)arguments[0]; - } - else if (arguments.length > 0 && arguments[0] instanceof Map && ((Map) arguments[0]).containsKey(ARGUMENT_FLUSH)) { - shouldFlush = GrailsClassUtils.getBooleanFromMap(ARGUMENT_FLUSH, ((Map) arguments[0])); - } - else { - final Map config = application.getFlatConfig(); - shouldFlush = Boolean.TRUE == config.get(AUTO_FLUSH_CONFIG_PROPERTY); - } - return shouldFlush; - } - - /** - * Performs automatic association retrieval - * @param domainClass The domain class to retrieve associations for - * @param target The target object - */ - @SuppressWarnings("unchecked") - private void autoRetrieveAssocations(GrailsDomainClass domainClass, Object target) { - BeanWrapper bean = new BeanWrapperImpl(target); - GrailsHibernateTemplate t = getHibernateTemplate(); - GrailsDomainClassProperty[] props = domainClass.getPersistentProperties(); - for (int i = 0; i < props.length; i++) { - GrailsDomainClassProperty prop = props[i]; - if (!prop.isManyToOne() && !prop.isOneToOne()) { - continue; - } - - Object propValue = bean.getPropertyValue(prop.getName()); - if (propValue == null || t.contains(propValue)) { - continue; - } - - GrailsDomainClass otherSide = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - prop.getType().getName()); - if (otherSide == null) { - continue; - } - - BeanWrapper propBean = new BeanWrapperImpl(propValue); - try { - Serializable id = (Serializable)propBean.getPropertyValue(otherSide.getIdentifier().getName()); - if (id != null) { - final Object propVal = t.get(prop.getType(), id); - if (propVal != null) { - bean.setPropertyValue(prop.getName(), propVal); - } - } - } - catch (InvalidPropertyException ipe) { - // property is not accessable - } - } - } - - /** - * Sets the flush mode to manual. which ensures that the database changes are not persisted to the database - * if a validation error occurs. If save() is called again and validation passes the code will check if there - * is a manual flush mode and flush manually if necessary - * - * @param domainClass The domain class - * @param target The target object that failed validation - * @param errors The Errors instance @return This method will return null signaling a validation failure - */ - protected Object handleValidationError(GrailsDomainClass domainClass, final Object target, Errors errors) { - // if a validation error occurs set the object to read-only to prevent a flush - setObjectToReadOnly(target); - if (domainClass instanceof DefaultGrailsDomainClass) { - DefaultGrailsDomainClass dgdc = (DefaultGrailsDomainClass) domainClass; - List<GrailsDomainClassProperty> associations = dgdc.getAssociations(); - for (GrailsDomainClassProperty association : associations) { - if (association.isOneToOne() || association.isManyToOne()) { - BeanWrapper bean = new BeanWrapperImpl(target); - Object propertyValue = bean.getPropertyValue(association.getName()); - if (propertyValue != null) { - setObjectToReadOnly(propertyValue); - } - } - } - } - setErrorsOnInstance(target, errors); - return null; - } - - /** - * Associates the Errors object on the instance - * - * @param target The target instance - * @param errors The Errors object - */ - protected void setErrorsOnInstance(Object target, Errors errors) { - if (target instanceof GroovyObject) { - ((GroovyObject)target).setProperty(ERRORS_PROPERTY,errors); - } - else { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - metaClass.setProperty(target.getClass() ,target, ERRORS_PROPERTY,errors, false, false); - } - } - - /** - * Checks whether validation should be performed - * @return true if the domain class should be validated - * @param arguments The arguments to the validate method - * @param domainClass The domain class - */ - @SuppressWarnings("rawtypes") - private boolean shouldValidate(Object[] arguments, GrailsDomainClass domainClass) { - if (domainClass == null) { - return false; - } - - if (arguments.length == 0) { - return true; - } - - if (arguments[0] instanceof Boolean) { - return (Boolean)arguments[0]; - } - - if (arguments[0] instanceof Map) { - Map argsMap = (Map)arguments[0]; - if (argsMap.containsKey(ARGUMENT_VALIDATE)) { - return GrailsClassUtils.getBooleanFromMap(ARGUMENT_VALIDATE, argsMap); - } - - return true; - } - - return true; - } - - /** - * Subclasses should override and perform a save operation, flushing the session if the second argument is true - * - * @param target The target object to save - * @param shouldFlush Whether to flush - * @return The target object - */ - protected abstract Object performSave(Object target, boolean shouldFlush); - - /** - * Subclasses should override and perform an insert operation, flushing the session if the second argument is true - * - * @param target The target object to save - * @param shouldFlush Whether to flush - * @return The target object - */ - protected abstract Object performInsert(Object target, boolean shouldFlush); -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java deleted file mode 100644 index 58b128c..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java +++ /dev/null
@@ -1,121 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.HibernateCriteriaBuilder; -import groovy.lang.Closure; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.metaclass.AbstractStaticMethodInvocation; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.HibernateSession; -import org.codehaus.groovy.grails.orm.hibernate.query.HibernateQuery; -import org.grails.datastore.gorm.finders.DynamicFinder; -import org.grails.datastore.gorm.finders.FinderMethod; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.hibernate.Criteria; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.util.Assert; - -/** - * Abstract base class for static persistent methods. - * - * @author Steven Devijver - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractStaticPersistentMethod extends AbstractStaticMethodInvocation implements FinderMethod { - - private ClassLoader classLoader; - private GrailsHibernateTemplate hibernateTemplate; - private SessionFactory sessionFactory; - protected final GrailsApplication application; - - protected AbstractStaticPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, Pattern pattern, GrailsApplication application, int defaultFlushMode) { - Assert.notNull(sessionFactory, "Session factory is required!"); - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.application = application; - setPattern(pattern); - this.classLoader = classLoader; - this.sessionFactory = sessionFactory; - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, application, defaultFlushMode); - } - - protected SessionFactory getSessionFactory() { - return sessionFactory; - } - - protected GrailsHibernateTemplate getHibernateTemplate() { - return hibernateTemplate; - } - - @Override - public Object invoke(Class clazz, String methodName, Object[] arguments) { - return invoke(clazz, methodName, (Closure) null, arguments); - } - - public Object invoke(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(clazz, methodName, additionalCriteria, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - public Object invoke(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(classLoader); - return doInvokeInternal(clazz, methodName, additionalCriteria, arguments); - } - finally { - Thread.currentThread().setContextClassLoader(originalClassLoader); - } - } - - protected Criteria getCriteria(HibernateDatastore datastore, GrailsApplication appliation, Session session, DetachedCriteria detachedCriteria, Closure additionalCriteria, Class<?> clazz) { - if (additionalCriteria != null) { - HibernateCriteriaBuilder builder = new HibernateCriteriaBuilder(clazz, session.getSessionFactory()); - builder.setGrailsApplication(appliation); - builder.setConversionService(datastore.getMappingContext().getConversionService()); - builder.setDefaultFlushMode(datastore.getDefaultFlushMode()); - return builder.buildCriteria(additionalCriteria); - } - - Criteria criteria = session.createCriteria(clazz); - if (detachedCriteria != null) { - HibernateSession hibernateSession = new HibernateSession(datastore, session.getSessionFactory()); - PersistentEntity persistentEntity = datastore.getMappingContext().getPersistentEntity(clazz.getName()); - if (persistentEntity != null) { - DynamicFinder.applyDetachedCriteria(new HibernateQuery(criteria, hibernateSession, persistentEntity), detachedCriteria); - } - } - hibernateTemplate.applySettings(criteria); - return criteria; - } - - protected abstract Object doInvokeInternal(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments); - - protected abstract Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments); -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java deleted file mode 100644 index e871033..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/CountByPersistentMethod.java +++ /dev/null
@@ -1,94 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; - -/** - * Dynamic method that allows counting the values of the specified property names - * - * eg. Account.countByBranch('London') // returns how many accounts are in london - * - * @author Graeme Rocher - */ -public class CountByPersistentMethod extends AbstractClausedStaticPersistentMethod { - - private static final String OPERATOR_OR = "Or"; - private static final String OPERATOR_AND = "And"; - - private static final Pattern METHOD_PATTERN = Pattern.compile("(countBy)(\\w+)"); - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - - public CountByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader) { - super(application, sessionFactory, classLoader, METHOD_PATTERN, OPERATORS, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Long doInvokeInternalWithExpressions(final Class clazz, final String methodName, final Object[] arguments, - final List expressions, final String operatorInUse, final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Long>() { - public Long doInHibernate(Session session) throws HibernateException, SQLException { - final Criteria crit = getCriteria(datastore, application, session, detachedCriteria, additionalCriteria, clazz); - crit.setProjection(Projections.rowCount()); - String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - Map argsMap = (arguments.length > 1 && (arguments[1] instanceof Map)) ? (Map) arguments[1] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argsMap, conversionService, false); - - populateCriteriaWithExpressions(crit, operator, expressions); - return (Long) crit.uniqueResult(); - } - }); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected void populateCriteriaWithExpressions(Criteria crit, String operator, List expressions) { - if (operator.equals(OPERATOR_OR)) { - Disjunction dis = Restrictions.disjunction(); - for (GrailsMethodExpression current : (List<GrailsMethodExpression>)expressions) { - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (GrailsMethodExpression current : (List<GrailsMethodExpression>)expressions) { - crit.add(current.getCriterion()); - } - } - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java deleted file mode 100644 index c515746..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteQueryPersistentMethod.java +++ /dev/null
@@ -1,206 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.core.convert.ConversionService; - -/** - * Allows the executing of arbitrary HQL queries. - * <p/> - * eg. Account.executeQuery("select distinct a.number from Account a where a.branch = ?", 'London') or - * Account.executeQuery("select distinct a.number from Account a where a.branch = :branch", [branch:'London']) - * - * @author Graeme Rocher - * @author Sergey Nebolsin - * @see <a href="http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html">http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html</a> - * @since 30-Apr-2006 - */ -public class ExecuteQueryPersistentMethod extends AbstractStaticPersistentMethod { - private static final String METHOD_SIGNATURE = "executeQuery"; - private static final Pattern METHOD_PATTERN = Pattern.compile("^executeQuery$"); - - private static final List<String> QUERY_META_PARAMS = Arrays.asList( - GrailsHibernateUtil.ARGUMENT_MAX, - GrailsHibernateUtil.ARGUMENT_OFFSET, - GrailsHibernateUtil.ARGUMENT_CACHE, - GrailsHibernateUtil.ARGUMENT_FLUSH_MODE, - GrailsHibernateUtil.ARGUMENT_TIMEOUT, - GrailsHibernateUtil.ARGUMENT_FETCH_SIZE, - GrailsHibernateUtil.ARGUMENT_READ_ONLY); - - private final ConversionService conversionService; - - public ExecuteQueryPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, METHOD_PATTERN, application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { - checkMethodSignature(clazz, arguments); - - final String query = arguments[0].toString(); - final Map queryMetaParams = extractQueryMetaParams(arguments); - final List positionalParams = extractPositionalParams(arguments); - final Map namedParams = extractNamedParams(arguments); - - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - // process paginate params - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_MAX)) { - Integer maxParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_MAX), Integer.class); - q.setMaxResults(maxParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_OFFSET)) { - Integer offsetParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_OFFSET), Integer.class); - q.setFirstResult(offsetParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_CACHE)) { - q.setCacheable((Boolean)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_CACHE)); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_FETCH_SIZE)) { - Integer fetchSizeParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_FETCH_SIZE), Integer.class); - q.setFetchSize(fetchSizeParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_TIMEOUT)) { - Integer timeoutParam = conversionService.convert(queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_TIMEOUT), Integer.class); - q.setTimeout(timeoutParam.intValue()); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_READ_ONLY)) { - q.setReadOnly((Boolean)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_READ_ONLY)); - } - if (queryMetaParams.containsKey(GrailsHibernateUtil.ARGUMENT_FLUSH_MODE)) { - q.setFlushMode((FlushMode)queryMetaParams.get(GrailsHibernateUtil.ARGUMENT_FLUSH_MODE)); - } - // process positional HQL params - int index = 0; - for (Object parameter : positionalParams) { - q.setParameter(index++, parameter instanceof CharSequence ? parameter.toString() : parameter); - } - - // process named HQL params - for (Object o : namedParams.entrySet()) { - Map.Entry entry = (Map.Entry) o; - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be of type String"); - } - String parameterName = (String) entry.getKey(); - if (!QUERY_META_PARAMS.contains(parameterName)) { - Object parameterValue = entry.getValue(); - if (parameterValue == null) { - throw new IllegalArgumentException("Named parameter [" + entry.getKey() + "] value may not be null"); - } - if (Collection.class.isAssignableFrom(parameterValue.getClass())) { - q.setParameterList(parameterName, (Collection) parameterValue); - } - else if (parameterValue.getClass().isArray()) { - q.setParameterList(parameterName, (Object[]) parameterValue); - } - else if (parameterValue instanceof CharSequence) { - q.setParameter(parameterName, parameterValue.toString()); - } - else { - q.setParameter(parameterName, parameterValue); - } - } - } - return q.list(); - } - }); - } - - @SuppressWarnings("rawtypes") - private void checkMethodSignature(Class clazz, Object[] arguments) { - boolean valid = true; - if (arguments.length < 1) valid = false; - else if (arguments.length == 3 && !(arguments[2] instanceof Map)) valid = false; - else if (arguments.length > 3) valid = false; - - if (!valid) throw new MissingMethodException(METHOD_SIGNATURE, clazz, arguments); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Map extractQueryMetaParams(Object[] arguments) { - Map result = new HashMap(); - int metaParamsIndex = 0; - if (arguments.length == 2 && arguments[1] instanceof Map) metaParamsIndex = 1; - else if (arguments.length == 3) metaParamsIndex = 2; - if (metaParamsIndex > 0) { - Map sourceMap = (Map) arguments[metaParamsIndex]; - for (String queryMetaParam : QUERY_META_PARAMS) { - if (sourceMap.containsKey(queryMetaParam)) { - result.put(queryMetaParam, sourceMap.get(queryMetaParam)); - } - } - } - return result; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private List extractPositionalParams(Object[] arguments) { - List result = new ArrayList(); - if (arguments.length < 2 || arguments[1] instanceof Map) return result; - if (arguments[1] instanceof Collection) { - result.addAll((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - result.addAll(Arrays.asList((Object[]) arguments[1])); - } - else { - result.add(arguments[1]); - } - return result; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Map extractNamedParams(Object[] arguments) { - Map result = new HashMap(); - if (arguments.length < 2 || !(arguments[1] instanceof Map)) return result; - result.putAll((Map) arguments[1]); - return result; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java deleted file mode 100644 index d0953a2..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ExecuteUpdatePersistentMethod.java +++ /dev/null
@@ -1,151 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * Allows the executing of arbitrary HQL updates. - * <p/> - * eg. Account.executeUpdate("delete from Account a where a.branch = ?", 'London') or - * Account.executeUpdate("delete from Account a where a.branch = :branch", [branch:'London']) - * - * @author Burt Beckwith - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public class ExecuteUpdatePersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_SIGNATURE = "executeUpdate"; - private static final Pattern METHOD_PATTERN = Pattern.compile("^executeUpdate$"); - - public ExecuteUpdatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, int defaultFlushMode) { - super(sessionFactory, classLoader, METHOD_PATTERN, application, defaultFlushMode); - } - - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @Override - protected Object doInvokeInternal(final Class clazz, final String methodName, Closure additionalCriteria, final Object[] arguments) { - - checkMethodSignature(clazz, arguments); - - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(arguments[0].toString()); - getHibernateTemplate().applySettings(q); - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); - if (sessionHolder != null && sessionHolder.hasTimeout()) { - q.setTimeout(sessionHolder.getTimeToLiveInSeconds()); - } - - // process positional HQL params - int index = 0; - for (Object parameter : extractPositionalParams(arguments)) { - q.setParameter(index++, parameter); - } - - // process named HQL params - for (Map.Entry entry : (Set<Map.Entry>)extractNamedParams(arguments).entrySet()) { - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be of type String"); - } - - String parameterName = (String)entry.getKey(); - Object parameterValue = entry.getValue(); - if (Collection.class.isAssignableFrom(parameterValue.getClass())) { - q.setParameterList(parameterName, (Collection)parameterValue); - } - else if (parameterValue.getClass().isArray()) { - q.setParameterList(parameterName, (Object[])parameterValue); - } - else if (parameterValue instanceof CharSequence) { - q.setParameter(parameterName, parameterValue.toString()); - } - else { - q.setParameter(parameterName, parameterValue); - } - } - return q.executeUpdate(); - } - }); - } - - private void checkMethodSignature(Class clazz, Object[] arguments) { - boolean valid = true; - if (arguments.length == 0 || arguments.length > 2) { - valid = false; - } - else if (arguments.length == 2 && !(arguments[1] instanceof Map || arguments[1] instanceof Collection)) { - valid = false; - } - - if (!valid) { - throw new MissingMethodException(METHOD_SIGNATURE, clazz, arguments); - } - } - - private List extractPositionalParams(Object[] arguments) { - if (arguments.length == 1 || arguments[1] instanceof Map) { - return Collections.EMPTY_LIST; - } - - List result = new ArrayList(); - if (arguments[1] instanceof Collection) { - result.addAll((Collection)arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - result.addAll(Arrays.asList((Object[])arguments[1])); - } - else { - result.add(arguments[1]); - } - - return result; - } - - private Map extractNamedParams(Object[] arguments) { - if (arguments.length == 1 || !(arguments[1] instanceof Map)) { - return Collections.EMPTY_MAP; - } - - return (Map)arguments[1]; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java deleted file mode 100644 index 985fe1e..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByBooleanPropertyPersistentMethod.java +++ /dev/null
@@ -1,49 +0,0 @@ -/* Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "findAll<booleanProperty>By*" static persistent method. This method allows querying for - * instances of grails domain classes based on a boolean property and any other arbitrary - * properties. - * - * eg. - * Account.findAllActiveByHolder("Joe Blogs"); // Where class "Account" has a properties called "active" and "holder" - * Account.findAllActiveByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "active', "holder" and "branch" - * - * In both of those queries, the query will only select Account objects where active=true. - * - * @author Jeff Brown - */ -public class FindAllByBooleanPropertyPersistentMethod extends FindAllByPersistentMethod { - - private static final String METHOD_PATTERN = "(findAll)((\\w+)(By)([A-Z]\\w*)|(\\w+))"; - - public FindAllByBooleanPropertyPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader); - setPattern(Pattern.compile(METHOD_PATTERN)); - } - - @Override - protected boolean firstExpressionIsRequiredBoolean() { - return true; - } -} \ No newline at end of file
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java deleted file mode 100644 index 985667d..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllByPersistentMethod.java +++ /dev/null
@@ -1,129 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Disjunction; -import org.hibernate.criterion.Restrictions; - -/** - * The "findBy*" static persistent method. This method allows querying for - * instances of grails domain classes based on their properties. This method returns a list of all found results - * - * eg. - * Account.findAllByHolder("Joe Blogs"); // Where class "Account" has a property called "holder" - * Account.findAllByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "holder" and "branch" - * - * @author Graeme Rocher - */ -public class FindAllByPersistentMethod extends AbstractClausedStaticPersistentMethod { - - private static final String OPERATOR_OR = "Or"; - private static final String OPERATOR_AND = "And"; - private static final String METHOD_PATTERN = "(findAllBy)([A-Z]\\w*)"; - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - private HibernateDatastore datastore; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindAllByPersistentMethod(HibernateDatastore datastore,GrailsApplication application, SessionFactory sessionFactory, ClassLoader classLoader) { - super(application, sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), OPERATORS, datastore.getMappingContext().getConversionService(), datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternalWithExpressions(final Class clazz, String methodName, - final Object[] arguments, final List expressions, String operatorInUse, - final DetachedCriteria detachedCriteria, final Closure additionalCriteria) { - - final String operator = OPERATOR_OR.equals(operatorInUse) ? OPERATOR_OR : OPERATOR_AND; - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - final Criteria c = getCriteria(datastore,application, session,detachedCriteria, additionalCriteria, clazz); - - Map argsMap = (arguments.length > 0 && (arguments[0] instanceof Map)) ? (Map) arguments[0] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argsMap, conversionService); - - if (operator.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - GrailsMethodExpression expression = (GrailsMethodExpression) expressions.remove(0); - c.add(expression.getCriterion()); - } - - Disjunction dis = Restrictions.disjunction(); - int numberOfForceNoResultsCriterion = 0; - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - if (GrailsMethodExpression.FORCE_NO_RESULTS == current.getCriterion()) { - numberOfForceNoResultsCriterion++; - } else { - dis.add(current.getCriterion()); - } - } - if (numberOfForceNoResultsCriterion > 0 && numberOfForceNoResultsCriterion == expressions.size()) { - return Collections.EMPTY_LIST; - } - c.add(dis); - } - else { - for (Object expression : expressions) { - GrailsMethodExpression current = (GrailsMethodExpression) expression; - if (GrailsMethodExpression.FORCE_NO_RESULTS == current.getCriterion()) { - return Collections.emptyList(); - } - c.add(current.getCriterion()); - } - } - - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - }); - } - - /** - * Indicates if the first expression in the query is a required boolean property and as such should - * be ANDed to the other expressions, not ORed. - * - * @return true if the first expression is a required boolean property, false otherwise - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.FindAllByBooleanPropertyPersistentMethod - */ - protected boolean firstExpressionIsRequiredBoolean() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java deleted file mode 100644 index a800315..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindAllPersistentMethod.java +++ /dev/null
@@ -1,294 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.util.GrailsNameUtils; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Example; -import org.springframework.core.convert.ConversionService; - -/** - * <p> - * The "findAll" persistent static method allows searching for instances using - * either an example instance or an HQL query. Max results and offset parameters could - * be specified. A GrailsQueryException is thrown if the query is not a valid query - * for the domain class. - * <p> - * Syntax: - * DomainClass.findAll(query, params?) - * DomainClass.findAll(query, params?, max) - * DomainClass.findAll(query, params?, max, offset) - * DomainClass.findAll(query, params?, [max:10, offset:5]) - * - * <p> - * Examples in Groovy: <code> - * // retrieves all accounts - * def a = Account.findAll() - * - * // retrieve all accounts ordered by account number - * def a = Account.findAll("from Account as a order by a.number asc") - * - * // retrieve first 10 accounts ordered by account number - * def a = Account.findAll("from Account as a order by a.number asc",10) - * - * // retrieve first 10 accounts ordered by account number started from 5th account - * def a = Account.findAll("from Account as a order by a.number asc",10,5) - * - * // retrieve first 10 accounts ordered by account number started from 5th account - * def a = Account.findAll("from Account as a order by a.number asc",[max:10,offset:5]) - * - * // with query parameters - * def a = Account.find("from Account as a where a.number = ? and a.branch = ?", [38479, "London"]) - * - * // with query named parameters - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"]) - * - * // with query named parameters and max results and offset - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"], 10, 5) - * - * // with query named parameters and max results and offset map - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"], [max:10, offset:5]) - * - * // query by example - * def a = new Account() - * a.number = 495749357 - * def a = Account.find(a) - * - * </code> - * - * @author Graeme Rocher - * @author Steven Devijver - * @author Sergey Nebolsin - * - * @since 0.1 - */ -public class FindAllPersistentMethod extends AbstractStaticPersistentMethod { - private final ConversionService conversionService; - - public FindAllPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile("^findAll$"), application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - if (arguments.length == 0) { - return getHibernateTemplate().loadAll(clazz); - } - - final Object arg = arguments[0] instanceof CharSequence ? arguments[0].toString() : arguments[0]; - - // if the arg is an instance of the class find by example - if (arg instanceof String) { - final String query = ((String) arg).trim(); - final String shortName = GrailsNameUtils.getShortName(clazz); - if (!query.matches("(?i)from(?-i)\\s+[" + clazz.getName() + "|" + shortName + "].*")) { - throw new GrailsQueryException("Invalid query [" + query + "] for domain class [" + clazz + "]"); - } - - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - - Object[] queryArgs = null; - Map queryNamedArgs = null; - int max = retrieveMaxValue(); - int offset = retrieveOffsetValue(); - boolean useCache = useCache(); - if (arguments.length > 1) { - if (arguments[1] instanceof Collection) { - queryArgs = GrailsClassUtils.collectionToObjectArray((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - queryArgs = (Object[]) arguments[1]; - } - else if (arguments[1] instanceof Map) { - queryNamedArgs = (Map) arguments[1]; - } - } - - if (queryArgs != null) { - for (int i = 0; i < queryArgs.length; i++) { - if (queryArgs[i] instanceof CharSequence) { - q.setParameter(i, queryArgs[i].toString()); - } else { - q.setParameter(i, queryArgs[i]); - } - } - } - if (queryNamedArgs != null) { - for (Object o : queryNamedArgs.entrySet()) { - Map.Entry entry = (Map.Entry) o; - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be String: " + queryNamedArgs); - } - String stringKey = (String) entry.getKey(); - // Won't try to bind these parameters since they are processed separately - if (GrailsHibernateUtil.ARGUMENT_MAX.equals(stringKey) || GrailsHibernateUtil.ARGUMENT_OFFSET.equals(stringKey) || GrailsHibernateUtil.ARGUMENT_CACHE.equals(stringKey)) - continue; - Object value = entry.getValue(); - if (value == null) { - q.setParameter(stringKey, null); - } else if (value instanceof CharSequence) { - q.setParameter(stringKey, value.toString()); - } else if (List.class.isAssignableFrom(value.getClass())) { - q.setParameterList(stringKey, (List) value); - } else if (value.getClass().isArray()) { - q.setParameterList(stringKey, (Object[]) value); - } else { - q.setParameter(stringKey, value); - } - } - } - if (max > 0) { - q.setMaxResults(max); - } - if (offset > 0) { - q.setFirstResult(offset); - } - q.setCacheable(useCache); - return q.list(); - } - - private boolean useCache() { - boolean useCache = getHibernateTemplate().isCacheQueries(); - if (arguments.length > 1 && arguments[arguments.length - 1] instanceof Map) { - useCache = retrieveBoolean(arguments[arguments.length - 1], GrailsHibernateUtil.ARGUMENT_CACHE); - } - return useCache; - } - - private int retrieveMaxValue() { - int result = -1; - if (arguments.length > 1) { - result = retrieveInt(arguments[1], GrailsHibernateUtil.ARGUMENT_MAX); - if (arguments.length > 2 && result == -1) { - result = retrieveInt(arguments[2], GrailsHibernateUtil.ARGUMENT_MAX); - } - } - return result; - } - - private int retrieveOffsetValue() { - int result = -1; - if (arguments.length > 1) { - if (isMapWithValue(arguments[1], GrailsHibernateUtil.ARGUMENT_OFFSET)) { - result = ((Number)((Map)arguments[1]).get(GrailsHibernateUtil.ARGUMENT_OFFSET)).intValue(); - } - if (arguments.length > 2 && result == -1) { - if (isMapWithValue(arguments[2], GrailsHibernateUtil.ARGUMENT_OFFSET)) { - result = retrieveInt(arguments[2], GrailsHibernateUtil.ARGUMENT_OFFSET); - } - else if (isIntegerOrLong(arguments[1]) && isIntegerOrLong(arguments[2])) { - result = ((Number)arguments[2]).intValue(); - } - } - if (arguments.length > 3 && result == -1) { - if (isIntegerOrLong(arguments[3])) { - result = ((Number)arguments[3]).intValue(); - } - } - } - return result; - } - - private boolean retrieveBoolean(Object param, String key) { - boolean value = false; - if (isMapWithValue(param, key)) { - value = conversionService.convert(((Map)param).get(key), Boolean.class); - } - return value; - } - - private int retrieveInt(Object param, String key) { - if (isMapWithValue(param, key)) { - return conversionService.convert(((Map) param).get(key),Integer.class); - } - if (isIntegerOrLong(param)) { - return ((Number)param).intValue(); - } - return -1; - } - - private boolean isIntegerOrLong(Object param) { - return (param instanceof Integer) || (param instanceof Long); - } - - private boolean isMapWithValue(Object param, String key) { - return (param instanceof Map) && ((Map)param).containsKey(key); - } - }); - } - - if (clazz.isAssignableFrom(arg.getClass())) { - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - Example example = Example.create(arg).ignoreCase(); - - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - crit.add(example); - - Map argsMap = (arguments.length > 1 && (arguments[1] instanceof Map)) ? (Map) arguments[1] : Collections.EMPTY_MAP; - GrailsHibernateUtil.populateArgumentsForCriteria(application,clazz, crit, argsMap, conversionService); - return crit.list(); - } - }); - } - - if (arguments[0] instanceof Map) { - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, (Map)arguments[0], conversionService); - return crit.list(); - } - }); - } - - throw new MissingMethodException(methodName, clazz, arguments); - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java deleted file mode 100644 index c0ee00c..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByBooleanPropertyPersistentMethod.java +++ /dev/null
@@ -1,50 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "find<booleanProperty>By*" static persistent method. This method allows querying for - * instances of grails domain classes based on a boolean property and any other arbitrary - * properties. This method returns the first result of the query. - * - * eg. - * Account.findActiveByHolder("Joe Blogs"); // Where class "Account" has a properties called "active" and "holder" - * Account.findActiveByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "active', "holder" and "branch" - * - * In both of those queries, the query will only select Account objects where active=true. - * - * @author Jeff Brown - */ -public class FindByBooleanPropertyPersistentMethod extends FindByPersistentMethod { - - private static final String METHOD_PATTERN = "(find)((\\w+)(By)([A-Z]\\w*)|(\\w++))"; - - public FindByBooleanPropertyPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader); - setPattern(Pattern.compile(METHOD_PATTERN)); - } - - @Override - protected boolean firstExpressionIsRequiredBoolean() { - return true; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java deleted file mode 100644 index b2c5a95..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindByPersistentMethod.java +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -/** - * The "findBy*" static persistent method. This method allows querying for - * instances of grails domain classes based on their properties. This method returns the first result of the query - * - * eg. - * Account.findByHolder("Joe Blogs"); // Where class "Account" has a property called "holder" - * Account.findByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "holder" and "branch" - * - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public class FindByPersistentMethod extends AbstractFindByPersistentMethod { - - private static final String METHOD_PATTERN = "(findBy)([A-Z]\\w*)"; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore,application,sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), OPERATORS); - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java deleted file mode 100644 index 0065135..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrCreateByPersistentMethod.java +++ /dev/null
@@ -1,89 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MissingMethodException; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -@SuppressWarnings("rawtypes") -public class FindOrCreateByPersistentMethod extends AbstractFindByPersistentMethod { - - private static final String METHOD_PATTERN = "(findOrCreateBy)([A-Z]\\w*)"; - - public FindOrCreateByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - this(datastore, application,sessionFactory, classLoader, METHOD_PATTERN); - } - - public FindOrCreateByPersistentMethod(HibernateDatastore datastore, GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader, String pattern) { - super(datastore, application,sessionFactory, classLoader, Pattern.compile(pattern), OPERATORS); - } - - @SuppressWarnings("unchecked") - @Override - protected Object doInvokeInternalWithExpressions(Class clazz, - String methodName, Object[] arguments, List expressions, - String operatorInUse, DetachedCriteria detachedCriteria, Closure additionalCriteria) { - boolean isValidMethod = true; - - if (OPERATOR_OR.equals(operatorInUse)) { - isValidMethod = false; - } - - Iterator iterator = expressions.iterator(); - while (isValidMethod && iterator.hasNext()) { - GrailsMethodExpression gme = (GrailsMethodExpression) iterator.next(); - isValidMethod = GrailsMethodExpression.EQUAL.equals(gme.type); - } - - if (!isValidMethod) { - throw new MissingMethodException(methodName, clazz, arguments); - } - Object result = super.doInvokeInternalWithExpressions(clazz, methodName, arguments, - expressions, operatorInUse, detachedCriteria, additionalCriteria); - - if (result == null) { - Map m = new HashMap(); - for (Object o : expressions) { - GrailsMethodExpression gme = (GrailsMethodExpression) o; - m.put(gme.getPropertyName(), gme.getArguments()[0]); - } - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(clazz); - result = metaClass.invokeConstructor(new Object[]{m}); - if (shouldSaveOnCreate()) { - metaClass.invokeMethod(result, "save", null); - } - } - - return result; - } - - protected boolean shouldSaveOnCreate() { - return false; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java deleted file mode 100644 index c1dad7d..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindOrSaveByPersistentMethod.java +++ /dev/null
@@ -1,40 +0,0 @@ -/* - * Copyright 2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.SessionFactory; - -public class FindOrSaveByPersistentMethod extends FindOrCreateByPersistentMethod { - - private static final String METHOD_PATTERN = "(findOrSaveBy)([A-Z]\\w*)"; - - /** - * Constructor. - * @param application - * @param sessionFactory - * @param classLoader - */ - public FindOrSaveByPersistentMethod(HibernateDatastore datastore,GrailsApplication application,SessionFactory sessionFactory, ClassLoader classLoader) { - super(datastore, application,sessionFactory, classLoader, METHOD_PATTERN); - } - - @Override - protected boolean shouldSaveOnCreate() { - return true; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java deleted file mode 100644 index 85e84df..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/FindPersistentMethod.java +++ /dev/null
@@ -1,208 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.util.GrailsNameUtils; -import groovy.lang.Closure; -import groovy.lang.MissingMethodException; - -import java.sql.SQLException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Example; -import org.springframework.core.convert.ConversionService; - -/** - * <p> - * The "find" persistent static method allows searching for instances using - * either an example instance or an HQL query. This method returns the first - * result of the query. A GrailsQueryException is thrown if the query is not a - * valid query for the domain class. - * - * <p> - * Examples in Groovy: <code> - * // retrieve the first account ordered by account number - * def a = Account.find("from Account as a order by a.number asc") - * - * // with query parameters - * def a = Account.find("from Account as a where a.number = ? and a.branch = ?", [38479, "London"]) - * - * // with query named parameters - * def a = Account.find("from Account as a where a.number = :number and a.branch = :branch", [number:38479, branch:"London"]) - - * // query by example - * def a = new Account() - * a.number = 495749357 - * def a = Account.find(a) - * - * </code> - * - * @author Graeme Rocher - * @author Sergey Nebolsin - */ -public class FindPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "^find$"; - private final ConversionService conversionService; - - public FindPersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), application, defaultFlushMode); - this.conversionService = conversionService; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - - if (arguments.length == 0) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - final Object arg = arguments[0] instanceof CharSequence ? arguments[0].toString() : arguments[0]; - - if (arg instanceof String) { - final String query = (String) arg; - final String shortName = GrailsNameUtils.getShortName(clazz); - if (!query.matches("(?i)from(?-i)\\s+[" + clazz.getName() + "|" + shortName + "].*")) { - throw new GrailsQueryException("Invalid query [" + query + "] for domain class [" + clazz + "]"); - } - - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Query q = session.createQuery(query); - getHibernateTemplate().applySettings(q); - Object[] queryArgs = null; - Map queryNamedArgs = null; - boolean useCache = useCache(arguments); - - if (arguments.length > 1) { - if (arguments[1] instanceof Collection) { - queryArgs = GrailsClassUtils.collectionToObjectArray((Collection) arguments[1]); - } - else if (arguments[1].getClass().isArray()) { - queryArgs = (Object[]) arguments[1]; - } - else if (arguments[1] instanceof Map) { - queryNamedArgs = (Map) arguments[1]; - } - } - if (queryArgs != null) { - for (int i = 0; i < queryArgs.length; i++) { - if (queryArgs[i] instanceof CharSequence) { - q.setParameter(i, queryArgs[i].toString()); - } - else { - q.setParameter(i, queryArgs[i]); - } - } - } - if (queryNamedArgs != null) { - for (Iterator it = queryNamedArgs.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - if (!(entry.getKey() instanceof String)) { - throw new GrailsQueryException("Named parameter's name must be String: " + - queryNamedArgs.toString()); - } - String stringKey = (String) entry.getKey(); - Object value = entry.getValue(); - - if (GrailsHibernateUtil.ARGUMENT_CACHE.equals(stringKey)) { - continue; - } - else if (value instanceof CharSequence) { - q.setParameter(stringKey, value.toString()); - } - else if (List.class.isAssignableFrom(value.getClass())) { - q.setParameterList(stringKey, (List) value); - } - else if (value.getClass().isArray()) { - q.setParameterList(stringKey, (Object[]) value); - } - else { - q.setParameter(stringKey, value); - } - } - } - // only want one result, could have used uniqueObject here - // but it throws an exception if its not unique which is undesirable - q.setMaxResults(1); - q.setCacheable(useCache); - List results = q.list(); - if (results.size() > 0) { - return GrailsHibernateUtil.unwrapIfProxy(results.get(0)); - } - return null; - } - - private boolean useCache(Object[] args) { - boolean useCache = getHibernateTemplate().isCacheQueries(); - if (args.length > 1 && args[args.length - 1] instanceof Map) { - Object param = args[args.length - 1]; - String key = GrailsHibernateUtil.ARGUMENT_CACHE; - boolean value = false; - if ((param instanceof Map) && ((Map)param).containsKey(key)) { - value = conversionService.convert(((Map)param).get(key), Boolean.class); - } - useCache = value; - } - return useCache; - } - }); - } - else if (clazz.isAssignableFrom(arg.getClass())) { - // if the arg is an instance of the class find by example - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - - Example example = Example.create(arg).ignoreCase(); - - Criteria crit = session.createCriteria(clazz); - getHibernateTemplate().applySettings(crit); - crit.add(example); - crit.setMaxResults(1); - List results = crit.list(); - if (results.size() > 0) { - return results.get(0); - } - return null; - } - }); - } - - throw new MissingMethodException(methodName, clazz, arguments); - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java deleted file mode 100644 index 1f98f9c..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListOrderByPersistentMethod.java +++ /dev/null
@@ -1,97 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Order; - -/** - * The "listOrderBy*" static persistent method. Allows ordered listing of instances based on their properties. - * - * eg. - * Account.listOrderByHolder(); - * Account.listOrderByHolder(max); // max results - * - * @author Graeme - */ -public class ListOrderByPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "(listOrderBy)(\\w+)"; - private final HibernateDatastore datastore; - - public ListOrderByPersistentMethod(HibernateDatastore datastore, GrailsApplication grailsApplication, SessionFactory sessionFactory, ClassLoader classLoader) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication, datastore.getDefaultFlushMode()); - this.datastore = datastore; - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod#doInvokeInternal(java.lang.Class, java.lang.String, java.lang.Object[]) - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected Object doInvokeInternal(final Class clazz, String methodName, final Closure additionalCriteria, final Object[] arguments) { - - Matcher match = getPattern().matcher(methodName); - match.find(); - - String nameInSignature = match.group(2); - final String propertyName = nameInSignature.substring(0,1).toLowerCase(Locale.ENGLISH) + nameInSignature.substring(1); - - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria crit = getCriteria(datastore, application, session, null, additionalCriteria, clazz); - - if (arguments != null && arguments.length > 0) { - if (arguments[0] instanceof Map) { - Map argMap = (Map)arguments[0]; - argMap.put(GrailsHibernateUtil.ARGUMENT_SORT,propertyName); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, crit, argMap, datastore.getMappingContext().getConversionService()); - } - else { - crit.addOrder(Order.asc(propertyName)); - } - } - else { - crit.addOrder(Order.asc(propertyName)); - } - crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return crit.list(); - } - }); - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java deleted file mode 100644 index 10eec0d..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ListPersistentMethod.java +++ /dev/null
@@ -1,90 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.gorm.DetachedCriteria; -import grails.orm.PagedResultList; -import groovy.lang.Closure; - -import java.sql.SQLException; -import java.util.Collections; -import java.util.Map; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.core.convert.ConversionService; - -/** - * The "list" persistent static method. This method lists of of the persistent - * instances up the maximum specified amount (if any) - * - * eg. - * Account.list(); // list all - * Account.list(max:10,offset:50,sort:"holder",order:"desc"); // list up to 10, offset by 50, sorted by holder and in descending order - * - * @author Graeme Rocher - */ -public class ListPersistentMethod extends AbstractStaticPersistentMethod { - - private static final String METHOD_PATTERN = "^list$"; - private final ConversionService conversionService; - - public ListPersistentMethod(GrailsApplication grailsApplication, SessionFactory sessionFactory, ClassLoader classLoader, ConversionService conversionService, int defaultFlushMode) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication, defaultFlushMode); - this.conversionService = conversionService; - } - - @Override - @SuppressWarnings("rawtypes") - protected Object doInvokeInternal(final Class clazz, String methodName, Closure additionalCriteria, final Object[] arguments) { - // and list up to the max - return getHibernateTemplate().executeFind(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Criteria c = session.createCriteria(clazz); - getHibernateTemplate().applySettings(c); - if (arguments.length > 0 && arguments[0] instanceof Map) { - Map argMap = (Map)arguments[0]; - if (argMap.containsKey(GrailsHibernateUtil.ARGUMENT_MAX)) { - c.setMaxResults(Integer.MAX_VALUE); - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argMap, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return new PagedResultList(getHibernateTemplate(), c); - } - - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, argMap, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - - GrailsHibernateUtil.populateArgumentsForCriteria(application, clazz, c, Collections.EMPTY_MAP, conversionService); - c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return c.list(); - } - }); - } - - @SuppressWarnings("rawtypes") - @Override - protected Object doInvokeInternal(Class clazz, String methodName, DetachedCriteria additionalCriteria, Object[] arguments) { - return doInvokeInternal(clazz,methodName, (Closure) null,arguments) ; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java deleted file mode 100644 index 4b31312..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/MergePersistentMethod.java +++ /dev/null
@@ -1,74 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.sql.SQLException; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -/** - * The merge() method follows the semantics of merge which attempts to "merge" an object - * with a long lived session. - * - * @author Graeme Rocher - * @since 0.3 - */ -public class MergePersistentMethod extends AbstractSavePersistentMethod { - - public static final String METHOD_SIGNATURE = "merge"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - - public MergePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore); - } - - public MergePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, GrailsDomainClass dc, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, dc, datastore); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod#performSave(java.lang.Object) - */ - @Override - protected Object performSave(final Object target, final boolean flush) { - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Object merged = session.merge(target); - session.lock(merged, LockMode.NONE); - - if (flush) { - session.flush(); - } - return merged; - } - }); - } - - @Override - protected Object performInsert(Object target, boolean shouldFlush) { - throw new IllegalArgumentException("The [insert] argument is not supported by the [merge] method"); - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java deleted file mode 100644 index c05b0ed..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/SavePersistentMethod.java +++ /dev/null
@@ -1,94 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import java.sql.SQLException; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -/** - * Follows the semantics of saveOrUpdate of scheduling the object for persistence when a flush occurs. - * - * @author Steven Devijver - * @author Graeme Rocher - * - * @since 0.1 - */ -public class SavePersistentMethod extends AbstractSavePersistentMethod { - - public static final String METHOD_SIGNATURE = "save"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - - public SavePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore); - } - - public SavePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, GrailsDomainClass domainClass, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, domainClass, datastore); - } - - @Override - protected Object performSave(final Object target, final boolean flush) { - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - session.saveOrUpdate(target); - if (flush) { - flushSession(session); - } - return target; - } - }); - } - - @Override - protected Object performInsert(final Object target, final boolean shouldFlush) { - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback<Object>() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - try { - ClosureEventTriggeringInterceptor.markInsertActive(); - session.save(target); - if (shouldFlush) { - flushSession(session); - } - return target; - } finally { - ClosureEventTriggeringInterceptor.resetInsertActive(); - } - } - }); - } - - protected void flushSession(Session session) throws HibernateException { - try { - session.flush(); - } catch (HibernateException e) { - // session should not be flushed again after a data acccess exception! - session.setFlushMode(FlushMode.MANUAL); - throw e; - } - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java deleted file mode 100644 index 8819ce1..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/ValidatePersistentMethod.java +++ /dev/null
@@ -1,178 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -import grails.validation.ValidationErrors; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.validation.AbstractPersistentConstraint; -import org.codehaus.groovy.grails.validation.CascadingValidator; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.SessionFactory; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; -import org.springframework.validation.FieldError; -import org.springframework.validation.ObjectError; -import org.springframework.validation.Validator; - -/** - * Validates an instance of a domain class against its constraints. - * - * @author Graeme Rocher - * @since 07-Nov-2005 - */ -public class ValidatePersistentMethod extends AbstractDynamicPersistentMethod { - - public static final String METHOD_SIGNATURE = "validate"; - public static final Pattern METHOD_PATTERN = Pattern.compile('^'+METHOD_SIGNATURE+'$'); - public static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"; - private static final String ARGUMENT_EVICT = "evict"; - private Validator validator; - private HibernateDatastore datastore; - - public ValidatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application) { - this(sessionFactory, classLoader, application, null, null); - } - - public ValidatePersistentMethod(SessionFactory sessionFactory, ClassLoader classLoader, - GrailsApplication application, Validator validator, HibernateDatastore datastore) { - super(METHOD_PATTERN, sessionFactory, classLoader, application, datastore.getDefaultFlushMode()); - Assert.notNull(application, "Constructor argument 'application' cannot be null"); - this.validator = validator; - this.datastore = datastore; - } - - @Override - @SuppressWarnings({"unchecked","rawtypes"}) - protected Object doInvokeInternal(final Object target, Object[] arguments) { - Errors errors = setupErrorsProperty(target); - - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, - target.getClass().getName()); - - if (validator == null && domainClass != null) { - validator = domainClass.getValidator(); - } - - if (validator == null) { - return true; - } - - Boolean valid = Boolean.TRUE; - // should evict? - boolean evict = false; - boolean deepValidate = true; - Set validatedFields = null; - List validatedFieldsList = null; - - if (arguments.length > 0) { - if (arguments[0] instanceof Boolean) { - evict = (Boolean)arguments[0]; - } - if (arguments[0] instanceof Map) { - Map argsMap = (Map)arguments[0]; - - if (argsMap.containsKey(ARGUMENT_DEEP_VALIDATE)) { - deepValidate = GrailsClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, argsMap); - } - - evict = GrailsClassUtils.getBooleanFromMap(ARGUMENT_EVICT, argsMap); - } - if (arguments[0] instanceof List) { - validatedFieldsList = (List)arguments[0]; - validatedFields = new HashSet(validatedFieldsList); - } - } - - fireEvent(target, validatedFieldsList); - - AbstractPersistentConstraint.sessionFactory.set(datastore.getSessionFactory()); - try { - if (deepValidate && (validator instanceof CascadingValidator)) { - ((CascadingValidator)validator).validate(target, errors, deepValidate); - } - else { - validator.validate(target,errors); - } - } - finally { - AbstractPersistentConstraint.sessionFactory.remove(); - } - - int oldErrorCount = errors.getErrorCount(); - errors = filterErrors(errors, validatedFields, target); - - if (errors.hasErrors()) { - valid = Boolean.FALSE; - if (evict) { - // if an boolean argument 'true' is passed to the method - // and validation fails then the object will be evicted - // from the session, ensuring it is not saved later when - // flush is called - if (getHibernateTemplate().contains(target)) { - getHibernateTemplate().evict(target); - } - } - } - - // If the errors have been filtered, update the 'errors' object attached to the target. - if (errors.getErrorCount() != oldErrorCount) { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - metaClass.setProperty(target, ERRORS_PROPERTY, errors); - } - - return valid; - } - - private void fireEvent(Object target, List<?> validatedFieldsList) { - ValidationEvent event = new ValidationEvent(datastore, target); - event.setValidatedFields(validatedFieldsList); - datastore.getApplicationContext().publishEvent(event); - } - - @SuppressWarnings("rawtypes") - private Errors filterErrors(Errors errors, Set validatedFields, Object target) { - if (validatedFields == null) return errors; - - ValidationErrors result = new ValidationErrors(target); - - final List allErrors = errors.getAllErrors(); - for (Object allError : allErrors) { - ObjectError error = (ObjectError) allError; - - if (error instanceof FieldError) { - FieldError fieldError = (FieldError) error; - if (!validatedFields.contains(fieldError.getField())) continue; - } - - result.addError(error); - } - - return result; - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java new file mode 100644 index 0000000..0ac02b2 --- /dev/null +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwarePojoEntityTuplizer.java
@@ -0,0 +1,50 @@ +/* + * Copyright 2014 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.codehaus.groovy.grails.orm.hibernate.proxy; + +import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.binding.EntityBinding; +import org.hibernate.property.Getter; +import org.hibernate.property.Setter; +import org.hibernate.proxy.ProxyFactory; +import org.hibernate.tuple.entity.EntityMetamodel; +import org.hibernate.tuple.entity.PojoEntityTuplizer; + +/** + * Ensures a Groovy aware proxy factory is registered + * + * @author Graeme Rocher + * @since 4.0 + */ +public class GroovyAwarePojoEntityTuplizer extends PojoEntityTuplizer { + + public GroovyAwarePojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { + super(entityMetamodel, mappedEntity); + } + public GroovyAwarePojoEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) { + super(entityMetamodel, mappedEntity); + } + + @Override + protected ProxyFactory buildProxyFactoryInternal(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { + return new GroovyAwareJavassistProxyFactory(); + } + + @Override + protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) { + return new GroovyAwareJavassistProxyFactory(); + } +}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java index a00deec..822baaa 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java
@@ -15,17 +15,9 @@ */ package org.codehaus.groovy.grails.orm.hibernate.proxy; -import java.lang.reflect.InvocationTargetException; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.support.proxy.EntityProxyHandler; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Hibernate; import org.hibernate.collection.internal.AbstractPersistentCollection; import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.HibernateProxyHelper; -import org.hibernate.proxy.LazyInitializer; /** * Implementation of the ProxyHandler interface for Hibernate. @@ -33,96 +25,36 @@ * @author Graeme Rocher * @since 1.2.2 */ -public class HibernateProxyHandler implements EntityProxyHandler { +public class HibernateProxyHandler extends SimpleHibernateProxyHandler { public boolean isInitialized(Object o) { - if (o instanceof HibernateProxy) { - return !((HibernateProxy)o).getHibernateLazyInitializer().isUninitialized(); - } - if (o instanceof PersistentCollection) { return ((PersistentCollection)o).wasInitialized(); } - return true; - } - - public boolean isInitialized(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); - return Hibernate.isInitialized(proxy); - } - catch (RuntimeException e) { - return false; - } + return super.isInitialized(o); } public Object unwrapIfProxy(Object instance) { - if (instance instanceof HibernateProxy) { - final HibernateProxy proxy = (HibernateProxy)instance; - return unwrapProxy(proxy); - } - if (instance instanceof AbstractPersistentCollection) { initialize(instance); return instance; } - return instance; - } - - public Object unwrapProxy(final HibernateProxy proxy) { - final LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer(); - if (lazyInitializer.isUninitialized()) { - lazyInitializer.initialize(); - } - final Object obj = lazyInitializer.getImplementation(); - if (obj != null) { - GrailsHibernateUtil.ensureCorrectGroovyMetaClass(obj,obj.getClass()); - } - return obj; - } - - public HibernateProxy getAssociationProxy(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.forClass(obj.getClass()).getPropertyValue(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (RuntimeException e) { - return null; - } + return super.unwrapIfProxy(instance); } public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (o instanceof AbstractPersistentCollection); + return super.isProxy(o) || (o instanceof AbstractPersistentCollection); } public void initialize(Object o) { - if (o instanceof HibernateProxy) { - final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer(); - if (hibernateLazyInitializer.isUninitialized()) { - hibernateLazyInitializer.initialize(); - } - } - else if (o instanceof AbstractPersistentCollection) { + if (o instanceof AbstractPersistentCollection) { final AbstractPersistentCollection col = (AbstractPersistentCollection)o; if (!col.wasInitialized()) { col.forceInitialization(); } } - } - - public Object getProxyIdentifier(Object o) { - if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); - } - return null; - } - - public Class<?> getProxiedClass(Object o) { - return HibernateProxyHelper.getClassWithoutInitializingProxy(o); + super.initialize(o); } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java index ab28980..f296584 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java
@@ -28,11 +28,11 @@ import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.grails.commons.GrailsClassUtils; import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormValidationApi; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; import org.grails.datastore.gorm.support.BeforeValidateHelper.BeforeValidateEventTriggerCaller; import org.grails.datastore.gorm.support.EventTriggerCaller; @@ -90,7 +90,7 @@ Map validateParams; MetaMethod validateMethod; TimestampProvider timestampProvider; - + public ClosureEventListener(Class<?> domainClazz, boolean failOnError, List failOnErrorPackages) { this(domainClazz, failOnError, failOnErrorPackages, new DefaultTimestampProvider()); } @@ -122,11 +122,11 @@ } validateParams = new HashMap(); - validateParams.put(ValidatePersistentMethod.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); + validateParams.put(AbstractHibernateGormValidationApi.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); - errorsProperty = domainMetaClass.getMetaProperty(AbstractDynamicPersistentMethod.ERRORS_PROPERTY); + errorsProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.ERRORS); - validateMethod = domainMetaClass.getMetaMethod(ValidatePersistentMethod.METHOD_SIGNATURE, + validateMethod = domainMetaClass.getMetaMethod("validate", new Object[] { Map.class }); try { @@ -155,7 +155,7 @@ shouldTimestamp = false; } } - + private boolean verifyTimestampFieldTypeSupport(Class<?> domainClazz, TimestampProvider timestampProvider, MetaProperty timestampField) { if(timestampProvider.supportsCreating(timestampField.getType())) { return true; @@ -253,7 +253,7 @@ public void onPostInsert(PostInsertEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postInsertEventListener == null) { return; } @@ -274,7 +274,7 @@ public void onPostUpdate(PostUpdateEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postUpdateEventListener == null) { return; } @@ -290,7 +290,7 @@ public void onPostDelete(PostDeleteEvent event) { final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); + AbstractHibernateGormInstanceApi.clearDisabledValidations(entity); if (postDeleteEventListener == null) { return; } @@ -316,7 +316,7 @@ } }); } - + public boolean onPreUpdate(final PreUpdateEvent event) { return doWithManualSession(event, new Closure<Boolean>(this) { @Override @@ -328,7 +328,7 @@ synchronizePersisterState(event, event.getState()); } handleTimestampingBeforeUpdate(event, entity); - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) + if (!AbstractHibernateGormInstanceApi.isAutoValidationDisabled(entity) && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { evict = true; if (failOnErrorEnabled) { @@ -372,7 +372,7 @@ } boolean evict = false; - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) + if (!AbstractHibernateGormInstanceApi.isAutoValidationDisabled(entity) && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { evict = true;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java index 8e6368e..c0a88dc 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java
@@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryProxy; import org.grails.datastore.mapping.core.Datastore; @@ -91,7 +92,6 @@ private ApplicationContext ctx; private Map<SessionFactory, HibernateDatastore> datastores; - private static final ThreadLocal<Boolean> insertActiveThreadLocal = new ThreadLocal<Boolean>(); /* public ClosureEventTriggeringInterceptor() { try { @@ -226,7 +226,7 @@ */ @Override protected Boolean getAssumedUnsaved() { - return insertActiveThreadLocal.get(); + return AbstractHibernateGormInstanceApi.getAssumedUnsaved(); } /** @@ -234,13 +234,13 @@ * to set a ThreadLocal variable that determines the value for getAssumedUnsaved(). */ public static void markInsertActive() { - insertActiveThreadLocal.set(true); + AbstractHibernateGormInstanceApi.markInsertActive(); } /** * Clears the ThreadLocal variable set by markInsertActive(). */ public static void resetInsertActive() { - insertActiveThreadLocal.remove(); + AbstractHibernateGormInstanceApi.resetInsertActive(); } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java index d2434c9..5c05598 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java
@@ -15,7 +15,7 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; -import org.codehaus.groovy.grails.web.servlet.mvc.RedirectEventListener; +import grails.web.mapping.mvc.RedirectEventListener; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java index 98b41e9..2d1e75a 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java
@@ -15,14 +15,10 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest; -import org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse; +import org.grails.web.servlet.mvc.GrailsWebRequest; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory; @@ -129,19 +125,6 @@ return; } - GrailsWebRequest webRequest = (GrailsWebRequest) request; - HttpServletResponse response = webRequest.getCurrentResponse(); - GrailsContentBufferingResponse contentBufferingResponse = getContentBufferingResponse(response); - if (contentBufferingResponse == null) { - super.afterCompletion(request, ex); - return; - } - - // if Sitemesh is still active disconnect the session, but don't close the session - if (!contentBufferingResponse.isActive()) { - super.afterCompletion(request, ex); - return; - } try { SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); @@ -157,19 +140,10 @@ } } finally { - AbstractSavePersistentMethod.clearDisabledValidations(); + AbstractHibernateGormInstanceApi.clearDisabledValidations(); } } - protected GrailsContentBufferingResponse getContentBufferingResponse(HttpServletResponse response) { - while (response instanceof HttpServletResponseWrapper) { - if (response instanceof GrailsContentBufferingResponse) { - return (GrailsContentBufferingResponse) response; - } - response = (HttpServletResponse) ((HttpServletResponseWrapper) response).getResponse(); - } - return null; - } public void setFlushMode(int flushMode) { this.flushMode = flushMode;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java index 7ebd844..fef8338 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java
@@ -15,7 +15,9 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; -import groovy.util.ConfigObject; +import grails.config.Config; +import grails.core.GrailsApplication; +import grails.core.support.GrailsApplicationAware; import java.sql.Connection; import java.sql.SQLException; @@ -23,9 +25,7 @@ import javax.sql.DataSource; -import org.codehaus.groovy.grails.commons.GrailsApplication; import org.codehaus.groovy.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException; -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.boot.registry.selector.internal.StrategySelectorImpl; @@ -91,7 +91,7 @@ connection = DataSourceUtils.getConnection(dataSource); try { - ConfigObject config = grailsApplication == null ? null : grailsApplication.getConfig(); + Config config = grailsApplication == null ? null : grailsApplication.getConfig(); Properties properties = config == null ? new Properties() : config.toProperties(); final DialectFactory dialectFactory = createDialectFactory(); final Connection finalConnection = connection;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java index 5a66dfd..e1c8495 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java
@@ -15,16 +15,15 @@ */ package org.codehaus.groovy.grails.orm.hibernate.support; +import grails.core.GrailsDomainClassProperty; +import grails.persistence.support.PersistenceContextInterceptor; import grails.validation.DeferredBindingActions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; +import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; +import org.grails.core.lifecycle.ShutdownOperations; import org.hibernate.FlushMode; -import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.internal.SessionImpl; @@ -105,7 +104,7 @@ } } finally { - AbstractSavePersistentMethod.clearDisabledValidations(); + AbstractHibernateGormInstanceApi.clearDisabledValidations(); } }
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java index 08c5d22..a548018 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java
@@ -16,11 +16,12 @@ import java.util.Map; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClassProperty; +import grails.validation.Constrained; +import grails.validation.ConstrainedProperty; import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.codehaus.groovy.grails.orm.hibernate.cfg.PropertyConfig; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -import org.codehaus.groovy.grails.validation.DefaultConstraintEvaluator; +import org.grails.validation.DefaultConstraintEvaluator; /** * Extends default implementation to add Hibernate specific exceptions. @@ -39,7 +40,7 @@ } @Override - protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, ConstrainedProperty cp) { + protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, Constrained cp) { final PropertyConfig propertyConfig = new GrailsDomainBinder().getPropertyConfig(p); boolean insertable = propertyConfig != null ? propertyConfig.isInsertable() : true;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java index d98458a..d1545af 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java
@@ -15,12 +15,12 @@ */ package org.codehaus.groovy.grails.orm.hibernate.validation; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.core.support.proxy.ProxyHandler; import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; -import org.codehaus.groovy.grails.support.proxy.ProxyHandler; -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.validation.GrailsDomainClassValidator; import org.hibernate.FlushMode; import org.hibernate.Hibernate; import org.hibernate.Session;
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java deleted file mode 100644 index d0910c5..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java +++ /dev/null
@@ -1,36 +0,0 @@ -/* - * Copyright 2004-2005 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.validation; - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.validation.Constraint; -import org.springframework.context.ApplicationContextAware; - -/** - * Defines a persistent constraint that evaluates the database. - * - * @author Graeme Rocher - * @since 10-Nov-2005 - */ -public interface PersistentConstraint extends Constraint, ApplicationContextAware { - - /** - * Obtains the HibernateTemplate. - * - * @return the template - */ - GrailsHibernateTemplate getHibernateTemplate(); -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java deleted file mode 100644 index a7c35ca..0000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java +++ /dev/null
@@ -1,63 +0,0 @@ -/* - * Copyright 2004-2005 Graeme Rocher - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.grails.orm.hibernate.validation; - -import org.codehaus.groovy.grails.exceptions.GrailsDomainException; -import org.codehaus.groovy.grails.validation.Constraint; -import org.codehaus.groovy.grails.validation.ConstraintFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.util.Assert; - -/** - * Creates PersistentConstraint instances ensuring that dependencies are provided. - * - * @author Graeme Rocher - * @since 0.4 - */ -public class PersistentConstraintFactory implements ConstraintFactory { - - private Class<?> constraintClass; - private ApplicationContext applicationContext; - - public PersistentConstraintFactory(ApplicationContext applicationContext, Class<?> persistentConstraint) { - - Assert.notNull(applicationContext, "Argument [applicationContext] cannot be null"); - - if (persistentConstraint == null || !PersistentConstraint.class.isAssignableFrom(persistentConstraint)) { - throw new IllegalArgumentException( - "Argument [persistentConstraint] must be an instance of " + PersistentConstraint.class.getName()); - } - - this.applicationContext = applicationContext; - this.constraintClass = persistentConstraint; - } - - public Constraint newInstance() { - try { - PersistentConstraint instance = (PersistentConstraint)constraintClass.newInstance(); - instance.setApplicationContext(applicationContext); - return instance; - } - catch (InstantiationException e) { - throw new GrailsDomainException("Error instantiating constraint [" + constraintClass + - "] during validation: " + e.getMessage(), e); - } - catch (IllegalAccessException e) { - throw new GrailsDomainException("Error instantiating constraint [" + constraintClass + - "] during validation: " + e.getMessage(), e); - } - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java index 9fc0731..03f26e6 100644 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java +++ b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java
@@ -19,22 +19,20 @@ import java.util.Collections; import java.util.List; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.exceptions.GrailsRuntimeException; -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; +import grails.core.GrailsApplication; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; +import grails.util.GrailsClassUtils; +import grails.validation.ConstrainedProperty; +import groovy.lang.Closure; + import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; +import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; import org.codehaus.groovy.runtime.InvokerHelper; -import org.hibernate.Criteria; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.TransientObjectException; +import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.core.exceptions.GrailsRuntimeException; +import org.grails.core.lifecycle.ShutdownOperations; +import org.hibernate.*; import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.springframework.beans.BeanWrapper; @@ -149,25 +147,25 @@ "domain classes and not custom user types or embedded instances"); } - GrailsHibernateTemplate hibernateTemplate = getHibernateTemplate(); + GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate )getHibernateTemplate(); hibernateTemplate.setFlushMode(GrailsHibernateTemplate.FLUSH_NEVER); - Assert.state(hibernateTemplate != null, - "Unable use [unique] constraint, no Hibernate SessionFactory found!"); - List<?> results = hibernateTemplate.executeFind(new GrailsHibernateTemplate.HibernateCallback<List<?>>() { - public List<?> doInHibernate(Session session) throws HibernateException { + List<?> results = hibernateTemplate.execute(new Closure<List<?>>(this) { + + public List<?> call(Object... args) { + Session session = (Session) args[0]; boolean shouldValidate = true; Class<?> constraintClass = constraintOwningClass; if (propertyValue != null && DomainClassArtefactHandler.isDomainClass(propertyValue.getClass())) { shouldValidate = session.contains(propertyValue); } if (shouldValidate) { - GrailsApplication application = (GrailsApplication) applicationContext.getBean(GrailsApplication.APPLICATION_ID); - GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE,constraintClass.getName()); + GrailsApplication application = (GrailsApplication) applicationContext.getBean(GrailsApplication.APPLICATION_ID); + GrailsDomainClass domainClass = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, constraintClass.getName()); if (domainClass != null && !domainClass.isRoot()) { GrailsDomainClassProperty property = domainClass.getPropertyByName(constraintPropertyName); while (property.isInherited() && domainClass != null) { domainClass = (GrailsDomainClass) application.getArtefact( - DomainClassArtefactHandler.TYPE,domainClass.getClazz().getSuperclass().getName()); + DomainClassArtefactHandler.TYPE, domainClass.getClazz().getSuperclass().getName()); if (domainClass != null) { property = domainClass.getPropertyByName(constraintPropertyName); } @@ -192,7 +190,7 @@ criteria.add(Restrictions.eq(constraintPropertyAlias + "." + identifierPropertyName, identifierPropertyValue)); } else { criteria = session.createCriteria(constraintClass) - .add(Restrictions.eq(constraintPropertyName, propertyValue)); + .add(Restrictions.eq(constraintPropertyName, propertyValue)); } if (uniquenessGroup != null) { @@ -204,15 +202,13 @@ try { // We are merely verifying that the object is not transient here session.lock(uniquenessGroupPropertyValue, LockMode.NONE); - } - catch (TransientObjectException e) { + } catch (TransientObjectException e) { shouldValidate = false; } } if (shouldValidate) { criteria.add(Restrictions.eq(uniquenessGroupPropertyName, uniquenessGroupPropertyValue)); - } - else { + } else { break; // we aren't validating, so no point continuing } } @@ -258,4 +254,15 @@ return uniquenessGroup; } + + @Override + public IHibernateTemplate getHibernateTemplate() { + SessionFactory sf = sessionFactory.get(); + if (sf == null) { + sf = applicationContext.getBean("sessionFactory", SessionFactory.class); + } + GrailsApplication app = applicationContext.getBean("grailsApplication", GrailsApplication.class); + GrailsHibernateTemplate hibernateTemplate = new GrailsHibernateTemplate(sf, app, GrailsHibernateTemplate.FLUSH_NEVER); + return hibernateTemplate; + } }
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy index 9a07d96..2d0f120 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy
@@ -17,13 +17,16 @@ def datastoreInitializer = new HibernateDatastoreSpringInitializer(Person) def applicationContext = new GenericApplicationContext() - def dataSource = new DriverManagerDataSource(Driver.name, "jdbc:h2:mem:grailsDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_DELAY=-1", 'sa', '') + def dataSource = new DriverManagerDataSource("jdbc:h2:mem:grailsDb1;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_DELAY=-1", 'sa', '') + dataSource.driverClassName = Driver.name applicationContext.beanFactory.registerSingleton("dataSource", dataSource) when:"The application context is configured" datastoreInitializer.configureForBeanDefinitionRegistry(applicationContext) + boolean refreshCalled = false applicationContext.refresh() + refreshCalled = true def conn = dataSource.getConnection() then:"The database tables are created correctly" @@ -50,7 +53,7 @@ cleanup: - if(applicationContext.isRunning()) { + if(refreshCalled && applicationContext.isRunning()) { applicationContext.stop() } @@ -60,7 +63,9 @@ given:"An initializer instance" def datastoreInitializer = new HibernateDatastoreSpringInitializer(Person) - def dataSource = new DriverManagerDataSource(Driver.name, "jdbc:h2:mem:grailsDb2;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_DELAY=-1", 'sa', '') + def dataSource = new DriverManagerDataSource("jdbc:h2:mem:grailsDb2;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_DELAY=-1", 'sa', '') + dataSource.driverClassName = Driver.name + when:"The application context is configured" datastoreInitializer.configureForDataSource(dataSource)
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy index c919214..9267338 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy
@@ -1,12 +1,12 @@ package org.codehaus.groovy.grails.compiler.gorm +import grails.compiler.ast.ClassInjector import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.DefaultGrailsDomainClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader import org.codehaus.groovy.control.MultipleCompilationErrorsException +import org.grails.compiler.injection.DefaultGrailsDomainClassInjector +import org.grails.compiler.injection.GrailsAwareClassLoader +import org.grails.core.DefaultGrailsDomainClass import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.GormValidationApi
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy index ae6c64f..f1fcd25 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.compiler.gorm -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader +import grails.compiler.ast.ClassInjector +import org.grails.compiler.injection.GrailsAwareClassLoader import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormValidationApi import org.grails.datastore.mapping.simple.SimpleMapDatastore
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy index 331bf90..1f2ddda 100755 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateTests.groovy
@@ -1,8 +1,8 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication import grails.gorm.tests.GormDatastoreSpec import junit.framework.Assert -import org.codehaus.groovy.grails.commons.GrailsApplication import org.grails.datastore.mapping.core.DatastoreUtils import org.hibernate.Session import org.hibernate.SessionFactory
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy index 4a993d6..1dc5ef0 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BasicArrayAndCollectionMappingTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.* /**
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy index 6729263..69ae6f1 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalListMappingTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication +import grails.core.DefaultGrailsApplication import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration import org.hibernate.FetchMode import org.hibernate.engine.spi.CascadeStyle
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy index 0daf708..639107a 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndCircularOneToManyTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy index 54c8dfe..4d1d29b 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOneToManyAndUnidirectionalOneToManyTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy index 6b9dcdd..21efb82 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/BidirectionalOnetoManyWithInheritanceRelationshipManagementTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy index 75c4869..5b6ca1d 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviour2Tests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy index e49edb8..1f49801 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CascadingDeleteBehaviourTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy index 0c2ebb2..d608071 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CharSequenceAndGormTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate import grails.gorm.tests.Plant -import org.codehaus.groovy.grails.web.util.StreamCharBuffer +import org.grails.buffer.StreamCharBuffer import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy index 87e87ec..a80ad14 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CompositeIdentifierWithAssociationsTests.groovy
@@ -76,9 +76,12 @@ } } +trait SomeTrait { + void foo(){} +} @Entity -class CompositeIdentifierWithAssociationsParent implements Serializable { +class CompositeIdentifierWithAssociationsParent implements Serializable, SomeTrait { Long id Long version @@ -118,4 +121,4 @@ String postCode CompositeIdentifierWithAssociationsParent parent static belongsTo = [parent:CompositeIdentifierWithAssociationsParent] -} \ No newline at end of file +}
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy index d0d92d5..cca44df 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomIdSpec.groovy
@@ -1,9 +1,9 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty import org.hibernate.id.IdentifierGenerationException import org.springframework.orm.hibernate4.HibernateSystemException
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy index 48121f0..9566cb7 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CyclicManyToManyWithInheritanceTests.groovy
@@ -1,7 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass - +import grails.core.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy index d28511b..5f995b2 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/GormSpec.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsApplication import grails.gorm.tests.GormDatastoreSpec -import org.codehaus.groovy.grails.commons.GrailsApplication import org.hibernate.SessionFactory import org.springframework.context.ApplicationContext import spock.lang.Shared
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy index f793bf3..7885dc8 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateCriteriaBuilderTests.groovy
@@ -1,11 +1,9 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.orm.HibernateCriteriaBuilder import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass - +import org.grails.core.artefact.DomainClassArtefactHandler import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy index a0df03f..2c1e235 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/JpaMappedDomainTests.groovy
@@ -1,7 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import grails.persistence.Entity - +import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id import javax.persistence.JoinColumn
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy index 5cd2994..4de74e3 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyLoadedOneToOneIdentifierTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.apache.commons.beanutils.PropertyUtils import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil +import org.grails.core.util.ClassPropertyFetcher import org.hibernate.Hibernate import org.hibernate.proxy.HibernateProxy @@ -19,6 +19,7 @@ @Test void testDynamicMethodOnProxiedObject() { + def cpf = ClassPropertyFetcher.forClass(LazyLoadedUserIdentifier) def user = LazyLoadedUser.newInstance(name:"Fred") assertNotNull user.save(flush:true) @@ -29,7 +30,7 @@ session.clear() id = LazyLoadedUserIdentifier.get(1) - def proxy = PropertyUtils.getProperty(id, "user") + def proxy = cpf.getPropertyValue(id, "user") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", Hibernate.isInitialized(proxy) assertNotNull "calling save() on the proxy should have worked",proxy.save() @@ -37,6 +38,7 @@ @Test void testMethodCallsOnProxiedObjects() { + def cpf = ClassPropertyFetcher.forClass(LazyLoadedUserIdentifier) def user = LazyLoadedUser.newInstance(name:"Fred") assertNotNull user.save(flush:true) @@ -47,7 +49,7 @@ id = LazyLoadedUserIdentifier.get(1) - def proxy = PropertyUtils.getProperty(id, "user") + def proxy = cpf.getPropertyValue(id, "user") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", Hibernate.isInitialized(proxy) assertEquals "Fred", proxy.name
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy index 806d86d..b3bcac6 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/LazyProxiedAssociationsWithInheritanceTests.groovy
@@ -1,8 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate import grails.persistence.Entity - -import org.apache.commons.beanutils.PropertyUtils +import org.grails.core.util.ClassPropertyFetcher import org.hibernate.proxy.HibernateProxy import static junit.framework.Assert.* @@ -29,7 +28,7 @@ @Test void testMethodCallsOnProxiedObjects() { - + def cpf = ClassPropertyFetcher.forClass(LazyProxiedAssociationsWithInheritanceBook) def addr = LazyProxiedAssociationsWithInheritanceAddress.newInstance(houseNumber:'52') def auth = LazyProxiedAssociationsWithInheritanceAuthor.newInstance(name:'Marc Palmer') assertNotNull addr.save() @@ -44,7 +43,7 @@ session.clear() book = LazyProxiedAssociationsWithInheritanceBook.get(1) - def proxy = PropertyUtils.getProperty(book, "author") + def proxy = cpf.getPropertyValue(book, "author") assertTrue "should be a hibernate proxy", (proxy instanceof HibernateProxy) assertFalse "proxy should not be initialized", org.hibernate.Hibernate.isInitialized(proxy) @@ -61,6 +60,7 @@ @Test void testSettersOnProxiedObjects() { + def cpf = ClassPropertyFetcher.forClass(LazyProxiedAssociationsWithInheritanceBook) def Author = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceAuthor.name).clazz def Address = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceAddress.name).clazz def Book = ga.getDomainClass(LazyProxiedAssociationsWithInheritanceBook.name).clazz @@ -80,7 +80,7 @@ book = Book.get(1) - def proxy = PropertyUtils.getProperty(book, "author") + def proxy = cpf.getPropertyValue(book, "author") // test setter with non-null value proxy.address.houseNumber = '123' book.save() @@ -96,7 +96,7 @@ // test setting property to null book = Book.get(1) - proxy = PropertyUtils.getProperty(book, "author") + proxy = cpf.getPropertyValue(book, "author") proxy.address.houseNumber = null book.save() @@ -111,7 +111,7 @@ // should delegate call to the closure defined in HibernatePluginSupport.enhanceProxy // this broke with previous code book = Book.get(1) - proxy = PropertyUtils.getProperty(book, "author") + proxy = cpf.getPropertyValue(book, "author") proxy.address = null book.save() session.flush()
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy index d5035cc..b2c60d2 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyAndOneToOneTests.groovy
@@ -1,6 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass + import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy index ed7286e..5e93b2c 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/ManyToManyWithMapTests.groovy
@@ -1,7 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.junit.Test import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy index f519e88..57b1c57 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/MappingDefaultsTests.groovy
@@ -1,10 +1,8 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder -import org.codehaus.groovy.grails.plugins.GrailsPlugin -import org.codehaus.groovy.grails.validation.ConstrainedProperty import org.hibernate.type.YesNoType import static junit.framework.Assert.*
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy index 7fe0c03..baca56e 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/OneToOneSelfReferencedViaInheritanceTests.groovy
@@ -1,6 +1,7 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass + import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy index cac450e..923005e 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/PersistenceMethodTests.groovy
@@ -1,12 +1,11 @@ package org.codehaus.groovy.grails.orm.hibernate +import grails.core.GrailsDomainClass import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass import org.codehaus.groovy.grails.orm.hibernate.exceptions.GrailsQueryException -import org.codehaus.groovy.grails.orm.hibernate.metaclass.FindByPersistentMethod import org.codehaus.groovy.runtime.metaclass.MethodSelectionException +import org.grails.core.artefact.DomainClassArtefactHandler import org.springframework.core.convert.ConversionFailedException import org.springframework.validation.Errors @@ -24,15 +23,6 @@ } @Test - void testMethodSignatures() { - FindByPersistentMethod findBy = new FindByPersistentMethod(grailsApplication.mainContext.hibernateDatastore, - grailsApplication, sessionFactory, new GroovyClassLoader()) - assertTrue findBy.isMethodMatch("findByFirstName") - assertTrue findBy.isMethodMatch("findByFirstNameAndLastName") - assertFalse findBy.isMethodMatch("rubbish") - } - - @Test void testSavePersistentMethod() { // init spring config @@ -317,7 +307,7 @@ assertEquals 1, returnList.size() // and case when automatic conversion cannot be applied - shouldFail(ConversionFailedException) { + shouldFail(MissingMethodException) { returnList = domainClass.findAllById("1.1") } @@ -606,14 +596,14 @@ // test find with max result namedArgs.clear() namedArgs.namesList = ["wilma","fred"] as Object[] - returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, [max:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue assertEquals 1, listResult.size() // test find with max result without params - returnValue = domainClass.findAll("from PersistentMethodTests as p", 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p", [max:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -643,7 +633,7 @@ // test find with offset namedArgs.clear() namedArgs.namesList = ["wilma","fred"] as Object[] - returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, 2, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p where p.firstName in (:namesList)", namedArgs, [max:1, offset:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -651,7 +641,7 @@ assertEquals 1, listResult.size() // test find with offset without params - returnValue = domainClass.findAll("from PersistentMethodTests as p", 2, 1) + returnValue = domainClass.findAll("from PersistentMethodTests as p", [max:1, offset:1]) assertNotNull returnValue assertEquals ArrayList, returnValue.getClass() listResult = returnValue @@ -783,12 +773,12 @@ domainClass.executeQuery() } - shouldFail(MissingMethodException) { + shouldFail(IllegalArgumentException) { domainClass.executeQuery("query", "param", [:], "4") } // test query with wrong third param type (must be Map) - shouldFail(MissingMethodException) { + shouldFail(IllegalArgumentException) { domainClass.executeQuery("query", "param", "wrong third param") } @@ -858,16 +848,11 @@ // test with multiple positional parameters listResult = domainClass.executeQuery( - "select distinct p from PersistentMethodTests as p " + - "where p.firstName=? and p.lastName=?", ["fred", "flintstone"]) + "select distinct p from PersistentMethodTests as p " + + "where p.firstName=? and p.lastName=?", ["fred", "flintstone"]) assertEquals 1, listResult.size() assertEquals "fred", listResult[0].getProperty("firstName") - def msg = shouldFail(IllegalArgumentException) { - domainClass.executeQuery 'select distinct p from PersistentMethodTests as p where p.firstName = :firstName and p.lastName = :lastName', [firstName: null, lastName: 'King'] - } - assertEquals 'Named parameter [firstName] value may not be null', msg - // Test that executeQuery does not mutate List and Map arguments (GRAILS-7841) paginateParams = [max: 1] domainClass.executeQuery("select p from PersistentMethodTests as p", paginateParams)
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy index 75e1e2c..a4a9d07 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/SortMappingTests.groovy
@@ -142,7 +142,6 @@ Long version String name - Set unibooks Set books static hasMany = [books:SortMappingBook] @@ -174,7 +173,6 @@ Long version String name - Set unibooks Set books static hasMany = [books:SortMappingBook2]
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy index 90e2235..baa7736 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/TwoCircularUnidirectionalOneToManyTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.GrailsDomainClass +import grails.core.GrailsDomainClass import static junit.framework.Assert.* import org.junit.Test
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy index e755679..af22ce6 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UndirectionalOneToManyMappingTests.groovy
@@ -22,7 +22,7 @@ a.addToBooks(MappedU2mBook.newInstance(title:"The Shining")) .addToBooks(MappedU2mBook.newInstance(title:"The Stand")) - .save(true) + .save(flush:true) assertEquals 2, MappedU2mBook.list().size() // now let's test the database state
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy index 1c37eb0..5cb7205 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/UnidirectionalOneToManyHibernateMappedTests.groovy
@@ -1,6 +1,6 @@ package org.codehaus.groovy.grails.orm.hibernate -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication +import grails.core.DefaultGrailsApplication import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration /**
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy index 26c4201..e9b4f8f 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/WithCriteriaMethodTests.groovy
@@ -49,7 +49,7 @@ Long version String name Set books - def relatesToMany = [books:WithCriteriaMethodBook] + static hasMany = [books:WithCriteriaMethodBook] boolean equals(obj) { name == obj?.name } int hashCode() { name ? name.hashCode() : super.hashCode() } String toString() { name }
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy index e76de35..b8a9695 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinderTests.groovy
@@ -15,17 +15,19 @@ */ package org.codehaus.groovy.grails.orm.hibernate.cfg +import grails.core.DefaultGrailsApplication +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty +import grails.plugins.GrailsPlugin +import grails.plugins.GrailsPluginManager +import grails.util.Holders +import grails.validation.ConstrainedProperty +import org.grails.core.DefaultGrailsDomainClass +import org.grails.plugins.MockGrailsPluginManager +import org.grails.support.MockApplicationContext + import java.lang.reflect.Field -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.codehaus.groovy.grails.plugins.MockGrailsPluginManager -import org.codehaus.groovy.grails.plugins.PluginManagerHolder -import org.codehaus.groovy.grails.support.MockApplicationContext -import org.codehaus.groovy.grails.validation.ConstrainedProperty import org.codehaus.groovy.grails.validation.TestClass import org.hibernate.cfg.ImprovedNamingStrategy import org.hibernate.mapping.Bag @@ -243,7 +245,7 @@ super.setUp() ExpandoMetaClass.enableGlobally() MockGrailsPluginManager pluginManager = new MockGrailsPluginManager() - PluginManagerHolder.setPluginManager(pluginManager) + Holders.setPluginManager(pluginManager) previousNamingStrategyClass = grailsDomainBinder.NAMING_STRATEGIES[GrailsDomainClassProperty.DEFAULT_DATA_SOURCE].getClass() } @@ -252,7 +254,7 @@ super.tearDown() grailsDomainBinder.NAMING_STRATEGIES.clear() grailsDomainBinder.NAMING_STRATEGIES[GrailsDomainClassProperty.DEFAULT_DATA_SOURCE] = ImprovedNamingStrategy.INSTANCE - PluginManagerHolder.setPluginManager(null) + Holders.setPluginManager(null) grailsDomainBinder.configureNamingStrategy previousNamingStrategyClass } @@ -818,11 +820,11 @@ def myPluginMap = [:] myPluginMap.getName = { -> 'MyPlugin' } - def myPlugin = myPluginMap as org.codehaus.groovy.grails.plugins.GrailsPlugin + def myPlugin = myPluginMap as GrailsPlugin def publisherPluginMap = [:] publisherPluginMap.getName = { -> 'Publisher' } - def publisherPlugin = publisherPluginMap as org.codehaus.groovy.grails.plugins.GrailsPlugin + def publisherPlugin = publisherPluginMap as GrailsPlugin def pluginManagerMap = [setApplicationContext: { }] def myPluginDomainClassNames = ['GadgetClass', 'MyPluginPersonClass'] @@ -841,7 +843,7 @@ // no config property specified def cfg = new ConfigSlurper().parse(''' ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) def config = getDomainConfig(grailsApplication, pluginManager) def persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -856,7 +858,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.table.prefix.enabled = true ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -871,7 +873,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.table.prefix.enabled = false ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -886,7 +888,7 @@ cfg = new ConfigSlurper().parse(''' grails.gorm.publisher.table.prefix.enabled = true ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name) @@ -902,7 +904,7 @@ grails.gorm.table.prefix.enabled = true grails.gorm.myPlugin.table.prefix.enabled = false ''') - grailsApplication.config = cfg + grailsApplication.config.merge(cfg) config = getDomainConfig(grailsApplication, pluginManager) persistentClass = config.getClassMapping("WidgetClass") assertEquals("widget_class", persistentClass.table.name)
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy deleted file mode 100644 index 57e689a..0000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractFindByPersistentMethodSpec.groovy +++ /dev/null
@@ -1,45 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.metaclass - -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.orm.hibernate.Customer -import org.codehaus.groovy.grails.orm.hibernate.GormSpec -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore -import org.grails.datastore.mapping.model.MappingContext -import org.hibernate.Criteria -import org.hibernate.SessionFactory -import org.hibernate.internal.CriteriaImpl - -import spock.lang.Issue - -class AbstractFindByPersistentMethodSpec extends GormSpec { - - @Issue('GRAILS-8762') - void "Test that findBy configures a limit of 1"() { - given:"A finder method" - final datastore = new HibernateDatastore(applicationContext.getBean(MappingContext), sessionFactory, grailsApplication.config) - datastore.applicationContext = applicationContext - def finder = new TestFindBy(datastore, grailsApplication) - when:"The finder is invoked" - CriteriaImpl c = finder.invoke(Customer, "findByName", "Bob") - - then: "ensure that the limit is one" - c.maxResults == 1 - } - - @Override - List getDomainClasses() { - [Customer] - } -} - -class TestFindBy extends AbstractFindByPersistentMethod { - - TestFindBy(HibernateDatastore datastore, GrailsApplication application) { - super(datastore, application, datastore.getSessionFactory(), Thread.currentThread().contextClassLoader, ~/(findBy)([A-Z]\w*)/, ["Or", "And"] as String[]) - } - - @Override - protected Object getResult(Criteria crit, boolean useLimit) { - return crit - } -}
diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/Setup.groovy index e3a9abf..c1b5c45 100644 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ b/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/Setup.groovy
@@ -1,12 +1,10 @@ package org.grails.datastore.gorm +import grails.core.DefaultGrailsApplication import groovy.sql.Sql +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.metaclass.MetaClassEnhancer import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager import org.codehaus.groovy.grails.orm.hibernate.GrailsSessionContext import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore @@ -20,6 +18,9 @@ import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint import org.codehaus.groovy.grails.validation.ConstrainedProperty +import org.grails.core.metaclass.MetaClassEnhancer + +//import org.codehaus.groovy.grails.plugins.web.api.ControllersDomainBindingApi import org.grails.datastore.gorm.config.GrailsDomainClassMappingContext import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.MappingContext
diff --git a/grails-datastore-gorm-hibernate4/src/test/resources/log4j.properties b/grails-datastore-gorm-hibernate4/src/test/resources/log4j.properties new file mode 100644 index 0000000..c3e4822 --- /dev/null +++ b/grails-datastore-gorm-hibernate4/src/test/resources/log4j.properties
@@ -0,0 +1,15 @@ + +# Enable logging for everything. Rarely useful +log4j.rootLogger=error, NULL +log4j.appender.NULL=org.apache.log4j.varia.NullAppender +log4j.appender.NULL.layout=org.apache.log4j.PatternLayout + + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + +log4j.logger.org.hibernate=debug,stdout +log4j.logger.org.hibernate.SQL=trace,stdout +log4j.logger.org.hibernate.type=trace,stdout + +log4j.logger.org.codehaus.groovy \ No newline at end of file
diff --git a/grails-datastore-gorm-jcr/src/main/groovy/grails/persistence/Entity.java b/grails-datastore-gorm-jcr/src/main/groovy/grails/persistence/Entity.java deleted file mode 100644 index c7e431b..0000000 --- a/grails-datastore-gorm-jcr/src/main/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,15 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Entity { -} \ No newline at end of file
diff --git a/grails-datastore-gorm-jpa/build.gradle b/grails-datastore-gorm-jpa/build.gradle index c7b4325..409020a 100644 --- a/grails-datastore-gorm-jpa/build.gradle +++ b/grails-datastore-gorm-jpa/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails
diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy deleted file mode 100644 index a363cfb..0000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy +++ /dev/null
@@ -1,57 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -import org.grails.datastore.mapping.model.types.OneToOne -import org.grails.datastore.mapping.proxy.EntityProxy - -class OneToOneSpec extends GormDatastoreSpec { - - def "Test persist and retrieve unidirectional many-to-one"() { - given:"A domain model with a many-to-one" - def person = new Person(firstName:"Fred", lastName: "Flintstone") - def pet = new Pet(name:"Dino", owner:person) - person.save() - pet.save(flush:true) - session.clear() - - when:"The association is queried" - pet = Pet.findByName("Dino") - - then:"The domain model is valid" - pet != null - pet.name == "Dino" - pet.ownerId == person.id - pet.owner.firstName == "Fred" - } - - def "Test persist and retrieve one-to-one with inverse key"() { - given:"A domain model with a one-to-one" - def face = new Face(name:"Joe") - def nose = new Nose(hasFreckles: true, face:face) - face.nose = nose - face.save(flush:true) - session.clear() - - when:"The association is queried" - face = Face.get(face.id) - def association = Face.gormPersistentEntity.getPropertyByName('nose') - then:"The domain model is valid" - association instanceof OneToOne - association.associatedEntity.javaClass == Nose - face != null - face.noseId == nose.id - face.nose != null - face.nose.hasFreckles == true - - when:"The inverse association is queried" - session.clear() - nose = Nose.get(nose.id) - - then:"The domain model is valid" - nose != null - nose.hasFreckles == true - nose.face != null - nose.face.name == "Joe" - } -} -
diff --git a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaSuite.groovy b/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaSuite.groovy index 08af12b..09a05be 100644 --- a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaSuite.groovy +++ b/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaSuite.groovy
@@ -14,6 +14,7 @@ import grails.gorm.tests.NamedQuerySpec import grails.gorm.tests.NegationSpec import grails.gorm.tests.OneToManySpec +import grails.gorm.tests.OneToOneSpec import grails.gorm.tests.OrderBySpec import grails.gorm.tests.PersistenceEventListenerSpec import grails.gorm.tests.ProxyLoadingSpec @@ -61,7 +62,8 @@ //SaveAllSpec, //DeleteAllSpec // PersistenceEventListenerSpec -UpdateWithProxyPresentSpec +//UpdateWithProxyPresentSpec + OneToOneSpec ]) class JpaSuite {
diff --git a/grails-datastore-gorm-mongo/build.gradle b/grails-datastore-gorm-mongo/build.gradle index cf29189..725aee9 100644 --- a/grails-datastore-gorm-mongo/build.gradle +++ b/grails-datastore-gorm-mongo/build.gradle
@@ -1,4 +1,4 @@ -version = "1.3.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails }
diff --git a/grails-datastore-gorm-mongodb/build.gradle b/grails-datastore-gorm-mongodb/build.gradle index c9db815..255e76e 100644 --- a/grails-datastore-gorm-mongodb/build.gradle +++ b/grails-datastore-gorm-mongodb/build.gradle
@@ -1,4 +1,4 @@ -version = "3.0.3.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { optional } @@ -26,6 +26,7 @@ exclude group:'oro',module:'oro' exclude group:'asm',module:'asm' exclude group:'cglib',module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'xalan',module:'serializer' exclude group:'org.springframework',module:'spring-core' exclude group:'org.springframework',module:'spring-tx'
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy b/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy index c533d8f..27b07c3 100644 --- a/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy +++ b/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy
@@ -18,15 +18,17 @@ import com.mongodb.Mongo import com.mongodb.MongoClientURI import com.mongodb.MongoOptions +import grails.core.GrailsApplication import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.InstanceFactoryBean import org.grails.datastore.gorm.bootstrap.AbstractDatastoreInitializer import org.grails.datastore.gorm.mongo.MongoGormEnhancer +import org.grails.datastore.gorm.mongo.bean.factory.DefaultMappingHolder import org.grails.datastore.gorm.mongo.bean.factory.GMongoFactoryBean import org.grails.datastore.gorm.mongo.bean.factory.MongoDatastoreFactoryBean import org.grails.datastore.gorm.mongo.bean.factory.MongoMappingContextFactoryBean import org.grails.datastore.mapping.transactions.DatastoreTransactionManager +import org.grails.spring.beans.factory.InstanceFactoryBean +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition import org.springframework.beans.factory.support.BeanDefinitionRegistry import org.springframework.context.ApplicationContext import org.springframework.context.support.GenericApplicationContext @@ -68,11 +70,11 @@ super(persistentClasses) } - MongoDbDataStoreSpringInitializer(Properties configuration, Collection<Class> persistentClasses) { + MongoDbDataStoreSpringInitializer(Map configuration, Collection<Class> persistentClasses) { super(configuration, persistentClasses) } - MongoDbDataStoreSpringInitializer(Properties configuration, Class... persistentClasses) { + MongoDbDataStoreSpringInitializer(Map configuration, Class... persistentClasses) { super(configuration, persistentClasses) } @@ -94,13 +96,13 @@ @Override Closure getBeanDefinitions(BeanDefinitionRegistry beanDefinitionRegistry) { return { - def config = configuration ? new ConfigSlurper().parse(configuration) : new ConfigObject() - def mongoConfig = config?.grails?.mongo?.clone() ?: config?.grails?.mongodb?.clone() - if(mongoConfig == null) mongoConfig = new ConfigObject() + String connectionString = configurationObject.getProperty('grails.mongodb.connectionString','') ?: null + Closure defaultMapping = configurationObject.getProperty('grails.mongodb.default.mapping',Closure, this.defaultMapping) + Map mongoOptions = configurationObject.getProperty('grails.mongodb.options', Map, null) + String hostSetting = configurationObject.getProperty('grails.mongodb.host', '') + Collection<String> replicaSetSetting = configurationObject.getProperty('grails.mongodb.replicaSet', Collection, []) + Collection<String> replicaPairSetting = configurationObject.getProperty('grails.mongodb.replicaPair', Collection, []) - - def cso = mongoConfig?.connectionString - def connectionString = cso ? cso?.toString() : null MongoClientURI mongoClientURI = null if(connectionString) { mongoClientURI = new MongoClientURI(connectionString) @@ -111,11 +113,11 @@ callable.delegate = delegate callable.call() - mongoMappingContext(MongoMappingContextFactoryBean) { + gormMongoMappingContext(MongoMappingContextFactoryBean) { defaultDatabaseName = databaseName grailsApplication = ref(GrailsApplication.APPLICATION_ID) - if (mongoConfig.default.mapping instanceof Closure) { - delegate.defaultMapping = this.defaultMapping + if (defaultMapping) { + delegate.defaultMapping = new DefaultMappingHolder(defaultMapping) } } @@ -124,12 +126,9 @@ } else if(!beanDefinitionRegistry.containsBeanDefinition(mongoOptionsBeanName)) { "$mongoOptionsBeanName"(MongoOptionsFactoryBean) { - if (mongoConfig?.options) { - def options = mongoConfig.remove("options") - if(options instanceof Map) { - for (option in options) { - setProperty(option.key, option.value) - } + if (mongoOptions) { + for (option in mongoOptions) { + setProperty(option.key, option.value) } } } @@ -138,46 +137,61 @@ if(mongo) { "$mongoBeanName"(InstanceFactoryBean, mongo) } - else if(!beanDefinitionRegistry.containsBeanDefinition(mongoBeanName)) { + else { - "gmongo"(GMongoFactoryBean) { - delegate.mongoOptions = ref("$mongoOptionsBeanName") - def mongoHost = mongoConfig?.get("host") + def existingBean = beanDefinitionRegistry.containsBeanDefinition(mongoBeanName) ? beanDefinitionRegistry.getBeanDefinition(mongoBeanName) : null + boolean registerMongoBean = false + if(existingBean instanceof AnnotatedBeanDefinition) { + AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition)existingBean + if(annotatedBeanDefinition.metadata.className == 'org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration') { - if (mongoConfig?.replicaSet instanceof Collection) { - def set = [] - for (server in mongoConfig.get("replicaSet")) { - set << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") - } - - replicaSetSeeds = set - } - else if (mongoConfig?.replicaPair instanceof Collection) { - def pair = [] - for (server in mongoConfig.get("replicaPair")) { - pair << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") - } - replicaPair = pair - } - else if(mongoClientURI) { - clientURI = mongoClientURI - } - else if (mongoHost) { - host = mongoHost - def mongoPort = mongoConfig?.get("port") - if (mongoPort) port = mongoPort - } - else { - host = "localhost" + registerMongoBean = true } } + else if(existingBean == null) { + registerMongoBean = true + } - "$mongoBeanName"(gmongo:"getMongo") + if(registerMongoBean) { + "gmongo"(GMongoFactoryBean) { + delegate.mongoOptions = ref("$mongoOptionsBeanName") + + if(mongoClientURI) { + clientURI = mongoClientURI + } + else if (replicaSetSetting) { + def set = [] + for (server in replicaSetSetting) { + set << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") + } + + replicaSetSeeds = set + } + else if (replicaPairSetting) { + def pair = [] + for (server in replicaPairSetting) { + pair << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") + } + replicaPair = pair + } + else if (hostSetting) { + host = hostSetting + Integer mongoPort = configurationObject.getProperty('grails.mongodb.port', Integer, null) + if (mongoPort) port = mongoPort + } + else { + host = "localhost" + } + } + + "$mongoBeanName"(gmongo:"getMongo") + } + } mongoDatastore(MongoDatastoreFactoryBean) { delegate.mongo = ref(mongoBeanName) - mappingContext = mongoMappingContext - config = mongoConfig.toProperties() + mappingContext = gormMongoMappingContext + config = configurationObject } "mongoTransactionManager"(DatastoreTransactionManager) { datastore = ref("mongoDatastore")
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/geo/Polygon.groovy b/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/geo/Polygon.groovy index 5c602d0..5848d02 100644 --- a/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/geo/Polygon.groovy +++ b/grails-datastore-gorm-mongodb/src/main/groovy/grails/mongodb/geo/Polygon.groovy
@@ -102,15 +102,15 @@ return new Polygon( [fromSingleCoordsList(coords)] ) // case (2) above } else if( ((List)coords[0])[0] instanceof Point){ - return new Polygon( coords.collect { List<Point> poly_ring -> + return new Polygon( coords.collect { poly_ring -> // each is a List<Point> - return fromSingleCoordsList(poly_ring) + return fromSingleCoordsList((List<Point>)poly_ring) }) // case (3) above } else if( ((List)coords[0])[0] instanceof List && ((List)((List)coords[0])[0])[0] instanceof Number ){ - return new Polygon( coords.collect { List<List<Number>> poly_ring -> + return new Polygon( coords.collect { poly_ring -> // each is a List<Point> - return fromSingleCoordsList(poly_ring) + return fromSingleCoordsList((List<List<Number>>)poly_ring) } ) // case (4) above } else {
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy deleted file mode 100644 index 4c80ff9..0000000 --- a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy +++ /dev/null
@@ -1,76 +0,0 @@ -/* Copyright (C) 2011 SpringSource -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package org.grails.datastore.gorm.mongo.config - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.mongo.MongoGormEnhancer -import org.grails.datastore.mapping.mongo.MongoDatastore -import org.grails.datastore.mapping.mongo.config.MongoMappingContext -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.support.GenericApplicationContext - -/** - * Support class for easing configuration of MongoDB - * - * @deprecated Use {@link grails.mongodb.bootstrap.MongoDbDataStoreSpringInitializer} instead - */ -@Deprecated -class MongoDatastoreConfigurer { - - /** - * Configures MongoDB for usage via GORM - * - * @param databaseName The database name - * @param classes The classes - * @param configuration The configuration - * @return The MongoDatastore instance - */ - static MongoDatastore configure(String databaseName, Class[] classes, Map configuration = Collections.emptyMap() ) { - ExpandoMetaClass.enableGlobally() - - def ctx = new GenericApplicationContext() - ctx.refresh() - return configure(ctx, databaseName, classes, configuration) - } - - static MongoDatastore configure(ConfigurableApplicationContext ctx, String databaseName, Class[] classes, Map configuration) { - final context = new MongoMappingContext(databaseName) - def grailsApplication = new DefaultGrailsApplication(classes, Thread.currentThread().getContextClassLoader()) - grailsApplication.initialise() - for (cls in classes) { - def validator = new GrailsDomainClassValidator() - validator.setGrailsApplication(grailsApplication) - validator.setMessageSource(ctx) - validator.setDomainClass(grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, cls.name)) - final entity = context.addPersistentEntity(cls) - context.addEntityValidator(entity, validator) - } - def mongoDatastore = new MongoDatastore(context, configuration, ctx) - mongoDatastore.afterPropertiesSet() - - def enhancer = new MongoGormEnhancer(mongoDatastore, new DatastoreTransactionManager(datastore: mongoDatastore)) - enhancer.enhance() - - mongoDatastore.applicationContext.addApplicationListener new DomainEventListener(mongoDatastore) - mongoDatastore.applicationContext.addApplicationListener new AutoTimestampEventListener(mongoDatastore) - - return mongoDatastore - } -}
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy index a11fc05..a211843 100644 --- a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy +++ b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy
@@ -70,7 +70,7 @@ return null } - abstract T createFromCoords(List coords) + abstract T createFromCoords(List<List<Double>> coords) @Override protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion value, DBObject nativeQuery) {
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/LineStringType.groovy b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/LineStringType.groovy index 9a28228..0711d69 100644 --- a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/LineStringType.groovy +++ b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/gorm/mongo/geo/LineStringType.groovy
@@ -3,6 +3,7 @@ import grails.mongodb.geo.LineString import grails.mongodb.geo.Point import groovy.transform.CompileStatic + import org.springframework.dao.DataAccessResourceFailureException /** @@ -18,7 +19,7 @@ } @Override - LineString createFromCoords(List coords) { + LineString createFromCoords(List<List<Double>> coords) { if(coords.size() < 2) throw new DataAccessResourceFailureException("Invalid polygon data returned: $coords") def points = coords.collect() { List<Double> pos -> new Point(pos.get(0), pos.get(1)) }
diff --git a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java index 9da2fb9..c40f1e2 100644 --- a/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java +++ b/grails-datastore-gorm-mongodb/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java
@@ -294,7 +294,7 @@ if (mappedForm != null) { List<MongoCollection.Index> indices = mappedForm.getIndices(); for (MongoCollection.Index index : indices) { - collection.ensureIndex(new BasicDBObject(index.getDefinition()), new BasicDBObject(index.getOptions())); + collection.createIndex(new BasicDBObject(index.getDefinition()), new BasicDBObject(index.getOptions())); } for (Map compoundIndex : mappedForm.getCompoundIndices()) { @@ -338,10 +338,10 @@ } // continue using deprecated method to support older versions of MongoDB if (options.toMap().isEmpty()) { - collection.ensureIndex(dbObject); + collection.createIndex(dbObject); } else { - collection.ensureIndex(dbObject, options); + collection.createIndex(dbObject, options); } } }
diff --git a/grails-datastore-gorm-mongodb/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy b/grails-datastore-gorm-mongodb/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy index ae5fc36..835ca72 100644 --- a/grails-datastore-gorm-mongodb/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy +++ b/grails-datastore-gorm-mongodb/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy
@@ -2,14 +2,14 @@ import com.gmongo.GMongo import com.mongodb.MongoClientURI -import org.codehaus.groovy.grails.commons.GrailsApplication +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication +import grails.plugins.DefaultGrailsPluginManager +import org.grails.core.artefact.DomainClassArtefactHandler import spock.lang.Specification import grails.spring.BeanBuilder -import org.codehaus.groovy.grails.plugins.DefaultGrailsPluginManager -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication import org.grails.datastore.mapping.mongo.config.MongoMappingContext import grails.gorm.tests.Person -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler /** */
diff --git a/grails-datastore-gorm-neo4j/build.gradle b/grails-datastore-gorm-neo4j/build.gradle index dc1d435..e9c5adc 100644 --- a/grails-datastore-gorm-neo4j/build.gradle +++ b/grails-datastore-gorm-neo4j/build.gradle
@@ -1,5 +1,4 @@ - version = "2.0.0-SNAPSHOT" -//version = "2.0.0-M02" +//version = "4.0.0.BUILD-SNAPSHOT" ext.neo4jVersion = "2.0.3" ext.gdmVersion = "2.0.7.RELEASE"
diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphPersistentEntity.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphPersistentEntity.groovy index eb62625..1cfdada 100644 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphPersistentEntity.groovy +++ b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphPersistentEntity.groovy
@@ -45,11 +45,16 @@ } public Collection<String> getLabels(domainInstance=null) { - Object objs = mappedForm.getLabels(); - def result = objs instanceof Object[] ? - objs.collect { getLabelFor(it, domainInstance) } : - [getLabelFor(objs, domainInstance)] - result.findAll { it } // remove nulls + Object labels = mappedForm.getLabels(); + + List objs = labels instanceof Object[] ? labels as List : [labels] + + // if labels consists solely of instance-dependent labels, add default label based on class name + if ( objs.every { (it instanceof Closure) && (it.maximumNumberOfParameters==2) }) { + objs << null // adding -> label defaults to discriminator + } + + objs.collect { getLabelFor(it, domainInstance) }.findAll { it } // remove nulls } private Object getLabelFor(Object obj, domainInstance) {
diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jGormEnhancer.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jGormEnhancer.groovy index 30fa9af..3a5f0e3 100644 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jGormEnhancer.groovy +++ b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jGormEnhancer.groovy
@@ -49,14 +49,29 @@ return api } - public static void amendMapWithUndeclaredProperties(Map<String, Object> simpleProps, Object pojo, MappingContext mappingContext) { + public static Map<String, List<Object>> amendMapWithUndeclaredProperties(Map<String, Object> simpleProps, Object pojo, MappingContext mappingContext) { GroovyObject obj = (GroovyObject) pojo; + Map<String, List<Object>> dynRelProps = [:].withDefault { [] } Map<String,Object> map = (Map) obj.getProperty(Neo4jGormEnhancer.UNDECLARED_PROPERTIES); if (map!=null) { for (Map.Entry<String,Object> entry : map.entrySet()) { - simpleProps.put(entry.getKey(), Neo4jUtils.mapToAllowedNeo4jType(entry.getValue(), mappingContext)); + if (mappingContext.isPersistentEntity(entry.getValue())) { + dynRelProps[entry.getKey()] << entry.getValue() + } else if (isCollectionWithPersistentEntities(entry.getValue(), mappingContext)) { + dynRelProps[entry.getKey()].addAll(entry.getValue()) + } else { + simpleProps.put(entry.getKey(), Neo4jUtils.mapToAllowedNeo4jType(entry.getValue(), mappingContext)); + } } } + dynRelProps + } + + static boolean isCollectionWithPersistentEntities(Object o, MappingContext mappingContext) { + if (!(o instanceof Collection)) { + return false; + } + return (!o.empty) && (o.every { mappingContext.isPersistentEntity(it) }) } } @@ -113,6 +128,11 @@ unwrappedInstance.metaClass."${Neo4jGormEnhancer.UNDECLARED_PROPERTIES}" = undeclaredProps } (val == null) ? undeclaredProps.remove(name) : undeclaredProps.put(name, val) + if (datastore.mappingContext.isPersistentEntity(val)) { + val.save() + } else if (Neo4jGormEnhancer.isCollectionWithPersistentEntities(val, datastore.mappingContext)) { + val.each { it.save() } + } if (unwrappedInstance instanceof DirtyCheckable) { ((DirtyCheckable)unwrappedInstance).markDirty(name) }
diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jUtils.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jUtils.groovy index 55ce568..84981b4 100644 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jUtils.groovy +++ b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jUtils.groovy
@@ -3,10 +3,6 @@ import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.types.* -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.DynamicRelationshipType import org.neo4j.graphdb.GraphDatabaseService import org.neo4j.graphdb.Node import org.neo4j.graphdb.Relationship @@ -21,28 +17,6 @@ abstract class Neo4jUtils { /** - * - * @return {@link org.neo4j.graphdb.RelationshipType}, {@link org.neo4j.graphdb.Direction} - */ - static List relationTypeAndDirection(Association association) { - Direction direction = Direction.OUTGOING - String relTypeName = relationshipTypeName(association) - - // switch direction and name if we have a bidi and ( (many2many with not owning side) or (onetomany)) - if (association.bidirectional && - ((association instanceof ManyToMany && (!association.owningSide)) || - association instanceof ManyToOne)) { - direction = Direction.INCOMING - relTypeName = relationshipTypeName(association.inverseSide) - } - [DynamicRelationshipType.withName(relTypeName), direction ] - } - - static String relationshipTypeName(Association association) { - association.name - } - - /** * dump a given node with all properties and relationships * @param node * @param logger
diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jMappingContextFactoryBean.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jMappingContextFactoryBean.groovy index 8ba7081..dd10bcf 100644 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jMappingContextFactoryBean.groovy +++ b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jMappingContextFactoryBean.groovy
@@ -15,6 +15,7 @@ package org.grails.datastore.gorm.neo4j.bean.factory import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean +import org.grails.datastore.gorm.neo4j.HashcodeEqualsAwareProxyFactory import org.grails.datastore.gorm.neo4j.Neo4jMappingContext import org.grails.datastore.mapping.model.MappingContext @@ -26,6 +27,6 @@ class Neo4jMappingContextFactoryBean extends AbstractMappingContextFactoryBean { protected MappingContext createMappingContext() { - new Neo4jMappingContext() + new Neo4jMappingContext(proxyFactory: new HashcodeEqualsAwareProxyFactory()) } }
diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurer.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurer.groovy index b1441e7..ee6cd0d 100644 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurer.groovy +++ b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurer.groovy
@@ -15,12 +15,14 @@ package org.grails.datastore.gorm.neo4j.plugin.support import org.apache.tomcat.jdbc.pool.PoolProperties +import org.grails.core.support.ClassEditor import org.grails.datastore.gorm.neo4j.engine.JdbcCypherEngine import org.grails.datastore.gorm.plugin.support.SpringConfigurer import org.grails.datastore.gorm.neo4j.bean.factory.Neo4jMappingContextFactoryBean import org.grails.datastore.gorm.neo4j.bean.factory.Neo4jDatastoreFactoryBean import org.apache.tomcat.jdbc.pool.DataSource +import org.springframework.beans.factory.config.CustomEditorConfigurer /** * Spring configurer for Neo4j @@ -48,7 +50,6 @@ def neo4jUrl = config?.url ?: "jdbc:neo4j:mem" def neo4jProperties = [:] - def m = neo4jUrl =~ /$JDBC_NEO4J_PREFIX(\w+)/ if (m.matches()) { @@ -57,9 +58,12 @@ def isHaMode = config.ha ?: false def factoryClassName = isHaMode ? "org.neo4j.graphdb.factory.HighlyAvailableGraphDatabaseFactory" : "org.neo4j.graphdb.factory.GraphDatabaseFactory" + + def factoryClazz = Thread.currentThread().contextClassLoader.loadClass(factoryClassName) + def factoryMethodName = isHaMode ? "newHighlyAvailableDatabaseBuilder" : "newEmbeddedDatabaseBuilder" - graphDbFactory(factoryClassName as Class) + graphDbFactory(factoryClazz) graphDbBuilder(graphDbFactory : factoryMethodName, config.location ?: neo4jDefaultLocation) graphDbBuilderFinal(graphDbBuilder: "setConfig", config.dbProperties ?: [:]) @@ -72,7 +76,6 @@ } neo4jProperties.putAll(config.dbProperties) - neo4jPoolConfiguration(PoolProperties) { url = neo4jUrl driverClassName = "org.neo4j.jdbc.Driver" @@ -102,6 +105,13 @@ } + // reverting the change done for fixing GRAILS-11112 + // since we supply a GraphDatabaseService instance to dbProperties we do not want + // it being converted to a String + customEditors(CustomEditorConfigurer) { + customEditors = [(Class.name): ClassEditor.name ] + } + } } }
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareCollection.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareCollection.java new file mode 100644 index 0000000..4dc7377 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareCollection.java
@@ -0,0 +1,196 @@ +package org.grails.datastore.gorm.neo4j; + +import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; +import org.grails.datastore.mapping.engine.EntityAccess; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.ManyToMany; + +import java.util.Collection; +import java.util.Iterator; + +/** + * A {@link java.util.Collection} implementation setting it's owner's dirty status upon + * modification of the set. Internally {@link org.grails.datastore.mapping.dirty.checking.DirtyCheckable} + * is used which is applied to all domain classes using an AST transformation. + */ +public abstract class DirtyCheckableAwareCollection<T> implements Collection<T> { + + private final EntityAccess owner; + private final Association association; + private final Collection<T> delegate; + private final Neo4jSession session; + private final boolean reversed; + private final String relType; + + protected DirtyCheckableAwareCollection(EntityAccess owner, Association association, Collection<T> delegate, Neo4jSession session) { + this.owner = owner; + this.association = association; + this.delegate = delegate; + this.session = session; + reversed = RelationshipUtils.useReversedMappingFor(association); + relType = RelationshipUtils.relationshipTypeUsedFor(association); + + for (T obj: delegate) { + session.addPendingInsert(new RelationshipPendingInsert(owner, relType, new EntityAccess(association.getAssociatedEntity(), obj), session.getNativeInterface())); + } + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(0); + } + + @Override + public Iterator<T> iterator() { + return delegate.iterator(); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public <T> T[] toArray(T[] ts) { + return delegate.toArray(ts); + } + + @Override + public boolean add(T t) { + boolean isAdded = delegate.add(t); + if (isAdded) { + markDirty(); + adoptGraphUponAdd(t); + } + return isAdded; + } + + protected void adoptGraphUponAdd(T t) { + if (session.getMappingContext().getProxyFactory().isProxy(t)) { + if (!isDomainInstance(t)) return; + } + EntityAccess target = new EntityAccess(association.getAssociatedEntity(), t); + if (association.isBidirectional()) { + if (association instanceof ManyToMany) { + Collection coll = (Collection) target.getProperty(association.getReferencedPropertyName()); + coll.add(owner.getEntity()); + } else { + target.setProperty(association.getReferencedPropertyName(), owner.getEntity()); + } + } + + if (target.getIdentifier() == null) { // non-persistent instance + session.persist(t); + } + + if (!reversed) { // prevent duplicated rels + session.addPendingInsert(new RelationshipPendingInsert(owner, relType, target, session.getNativeInterface())); + } + } + + /** + * UpdateWithProxyPresentSpec from TCK forces usage of {@link org.grails.datastore.gorm.proxy.GroovyProxyFactory}, + * it's isProxy method is not 100% solid so we need to workaround here + * @param t + * @return + */ + private boolean isDomainInstance(T t) { + boolean isDomainInstance = false; + for (PersistentEntity pe: session.getMappingContext().getPersistentEntities()) { + if (pe.getJavaClass().equals(t.getClass())) { + isDomainInstance = true; + } + } + return isDomainInstance; + } + + @Override + public boolean remove(Object o) { + boolean isDeleted = delegate.remove(o); + if (isDeleted) { + markDirty(); + adoptGraphUponRemove(o); + } + return isDeleted; + + } + + protected void adoptGraphUponRemove(Object o) { + if (session.getMappingContext().getProxyFactory().isProxy(o)) { + return; + } + if (!reversed) { + session.addPendingInsert(new RelationshipPendingDelete(owner, relType, + new EntityAccess(association.getAssociatedEntity(), o), + session.getNativeInterface())); + } + } + + @Override + public boolean containsAll(Collection<?> objects) { + return delegate.containsAll(objects); + } + + @Override + public boolean addAll(Collection<? extends T> ts) { + boolean changed = delegate.addAll(ts); + if (changed) { + markDirty(); + } + return changed; + } + + public boolean addAll(Iterable<T> objects) { + boolean result = false; + for (T obj : objects) { + result |= add(obj); + } + return result; + } + + @Override + public boolean removeAll(Collection<?> objects) { + markDirty(); + return delegate.removeAll(objects); + } + + @Override + public boolean retainAll(Collection<?> objects) { + markDirty(); + return delegate.retainAll(objects); + } + + @Override + public void clear() { + markDirty(); + delegate.clear(); + } + + protected void markDirty() { + Object ownerEntity = owner.getEntity(); + if (ownerEntity instanceof DirtyCheckable) { + ((DirtyCheckable) ownerEntity).markDirty(association.getName()); + } + } + + /*@Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + }*/ +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareList.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareList.java new file mode 100644 index 0000000..52c1977 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareList.java
@@ -0,0 +1,89 @@ +package org.grails.datastore.gorm.neo4j; + +import org.grails.datastore.mapping.engine.EntityAccess; +import org.grails.datastore.mapping.model.types.Association; + +import java.util.*; + +/** + * A {@link java.util.Set} implementation setting it's owner's dirty status upon + * modification of the set. Internally {@link org.grails.datastore.mapping.dirty.checking.DirtyCheckable} + * is used which is applied to all domain classes using an AST transformation + */ +public class DirtyCheckableAwareList<T> extends DirtyCheckableAwareCollection<T> implements List<T> { + + private final List<T> delegate; + + public DirtyCheckableAwareList(EntityAccess owner, Association association, List<T> delegate, Neo4jSession session) { + super(owner, association, delegate, session); + this.delegate = delegate; + } + + @Override + public boolean addAll(int i, Collection<? extends T> ts) { + boolean added = delegate.addAll(i, ts); + if (added) { + markDirty(); + for (T t :ts) { + adoptGraphUponAdd(t); + } + } + return added; + } + + @Override + public T get(int i) { + return delegate.get(i); + } + + @Override + public T set(int i, T t) { + T old = delegate.set(i, t); + if (!t.equals(old)) { + markDirty(); + adoptGraphUponRemove(old); + adoptGraphUponAdd(t); + } + return old; + } + + @Override + public void add(int i, T t) { + markDirty(); + delegate.add(i, t); + adoptGraphUponAdd(t); + } + + @Override + public T remove(int i) { + markDirty(); + T removed = delegate.remove(i); + adoptGraphUponRemove(removed); + return removed; + } + + @Override + public int indexOf(Object o) { + return delegate.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return delegate.lastIndexOf(o); + } + + @Override + public ListIterator<T> listIterator() { + return delegate.listIterator(); + } + + @Override + public ListIterator<T> listIterator(int i) { + return delegate.listIterator(i); + } + + @Override + public List<T> subList(int i, int i2) { + return delegate.subList(i, i2); + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareSet.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareSet.java new file mode 100644 index 0000000..b79b94e --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/DirtyCheckableAwareSet.java
@@ -0,0 +1,22 @@ +package org.grails.datastore.gorm.neo4j; + +import org.grails.datastore.mapping.engine.EntityAccess; +import org.grails.datastore.mapping.model.types.Association; + +import java.util.Set; + +/** + * A {@link java.util.Set} implementation setting it's owner's dirty status upon + * modification of the set. Internally {@link org.grails.datastore.mapping.dirty.checking.DirtyCheckable} + * is used which is applied to all domain classes using an AST transformation + */ +public class DirtyCheckableAwareSet<T> extends DirtyCheckableAwareCollection<T> implements Set<T> { + + private final Set<T> delegate; + + public DirtyCheckableAwareSet(EntityAccess owner, Association association, Set<T> delegate, Neo4jSession session) { + super(owner, association, delegate, session); + this.delegate = delegate; + } + +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/HashcodeEqualsAwareProxyFactory.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/HashcodeEqualsAwareProxyFactory.java new file mode 100644 index 0000000..4df6b9e --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/HashcodeEqualsAwareProxyFactory.java
@@ -0,0 +1,29 @@ +package org.grails.datastore.gorm.neo4j; + +import javassist.util.proxy.MethodHandler; +import org.grails.datastore.mapping.core.Session; +import org.grails.datastore.mapping.proxy.JavassistProxyFactory; +import org.grails.datastore.mapping.proxy.SessionEntityProxyMethodHandler; + +import java.io.Serializable; + +/** + * extends {@link org.grails.datastore.mapping.proxy.JavassistProxyFactory} to capture method calls `hashCode` and `equals` + * without expanding the proxy + */ +public class HashcodeEqualsAwareProxyFactory extends JavassistProxyFactory { + + @Override + protected MethodHandler createMethodHandler(Session session, Class cls, Class proxyClass, final Serializable id) { + return new SessionEntityProxyMethodHandler(proxyClass, session, cls, id) { + protected Object invokeEntityProxyMethods(Object self, String methodName, Object[] args) { + if (methodName.equals("hashCode")) { + return id.hashCode(); + } else { + return super.invokeEntityProxyMethods(self, methodName, args); + } + } + }; + } + +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEnititySet.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEnititySet.java deleted file mode 100644 index b3d1977..0000000 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEnititySet.java +++ /dev/null
@@ -1,173 +0,0 @@ -package org.grails.datastore.gorm.neo4j; - -import org.grails.datastore.gorm.neo4j.engine.CypherResult; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.ManyToMany; -import org.grails.datastore.mapping.proxy.ProxyFactory; - -import java.util.*; - -/** - * Created by stefan on 20.03.14. - */ -public class LazyEnititySet<T> implements Set<T> { - - private final ProxyFactory proxyFactory; - private final Neo4jSession session; - private final EntityAccess owner; - private final Set<T> delegate = new HashSet<T>(); - private final Association association; - private boolean initialized = false; - private boolean reversed; - private String relType; - - public LazyEnititySet(EntityAccess owner, Association association, ProxyFactory proxyFactory, Neo4jSession session) { - this.owner = owner; - this.association = association; - this.proxyFactory = proxyFactory; - this.session = session; - reversed = RelationshipUtils.useReversedMappingFor(association); - relType = RelationshipUtils.relationshipTypeUsedFor(association); - } - - private void initialize() { - if (!initialized) { - initialized = true; - String cypher = CypherBuilder.findRelationshipEndpointIdsFor(association); - CypherResult result = session.getNativeInterface().execute(cypher, Collections.singletonList(owner.getIdentifier())); - - Class<T> clazz = association.getAssociatedEntity().getJavaClass(); - for (Map<String, Object> row : result) { - Long endpoint = (Long) row.get("id"); - delegate.add( proxyFactory.createProxy(session, clazz, endpoint)); - } - } - } - - @Override - public int size() { - initialize(); - return delegate.size(); - } - - @Override - public boolean isEmpty() { - initialize(); - return delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - initialize(); - return delegate.contains(o); - } - - @Override - public Iterator iterator() { - initialize(); - return delegate.iterator(); - } - - @Override - public Object[] toArray() { - initialize(); - return delegate.toArray(); - } - - @Override - public boolean add(Object o) { - initialize(); - boolean isNew = delegate.add((T) o); - if (isNew) { - EntityAccess target = new EntityAccess(association.getAssociatedEntity(), o); - - if (association.isBidirectional()) { - if (association instanceof ManyToMany) { - Collection coll = (Collection) target.getProperty(association.getReferencedPropertyName()); - coll.add(owner.getEntity()); - } else { - target.setProperty(association.getReferencedPropertyName(), owner.getEntity()); - } - } - - if (target.getIdentifier()==null) { // non-persistent instance - session.persist(o); - } - - if (!reversed) { // prevent duplicated rels - session.addPendingInsert(new RelationshipPendingInsert(owner, relType, target, session.getNativeInterface())); - } - - markDirty(); - - } - return isNew; - } - - @Override - public boolean remove(Object o) { - boolean isDeleted = delegate.remove(o); - if (isDeleted && (!reversed)) { - session.addPendingInsert(new RelationshipPendingDelete(owner, relType, - new EntityAccess(association.getAssociatedEntity(), o), - session.getNativeInterface())); - } - if (isDeleted) { - markDirty(); - } - return isDeleted; - } - - @Override - public boolean addAll(Collection collection) { - return addAll((Iterable)collection); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - - } - - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); -// return false; - } - - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); -// return false; - } - - @Override - public boolean containsAll(Collection collection) { - throw new UnsupportedOperationException(); -// return false; - } - - @Override - public T[] toArray(Object[] objects) { - throw new UnsupportedOperationException(); -// return new T[0]; - } - - public boolean addAll(Iterable objects) { - boolean hasChanged = false; - for (Object object: objects) { - hasChanged |= add(object); - } - return hasChanged; - } - - private void markDirty() { - Object entity = owner.getEntity(); - if (entity instanceof DirtyCheckable) { - ((DirtyCheckable) entity).markDirty(association.getName()); - } - } - -}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEntitySetToSetConverter.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEntitySetToSetConverter.java deleted file mode 100644 index 1721fda..0000000 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/LazyEntitySetToSetConverter.java +++ /dev/null
@@ -1,16 +0,0 @@ -package org.grails.datastore.gorm.neo4j; - -import org.springframework.core.convert.converter.Converter; - -import java.util.Set; - -/** - * bypass the default CollectionToCollectionConverter in order to not expand proxies -*/ -public class LazyEntitySetToSetConverter implements Converter<LazyEnititySet, Set> { - - @Override - public Set convert(LazyEnititySet source) { - return source; - } -}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jEntityPersister.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jEntityPersister.java index 9d857d8..6ce7422 100644 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jEntityPersister.java +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jEntityPersister.java
@@ -3,6 +3,7 @@ import groovy.lang.GroovyObject; import org.grails.datastore.gorm.neo4j.engine.CypherEngine; import org.grails.datastore.gorm.neo4j.engine.CypherResult; +import org.grails.datastore.gorm.neo4j.parsers.PlingStemmer; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; import org.grails.datastore.mapping.engine.EntityAccess; @@ -96,31 +97,42 @@ int longestInheritenceChain = -1; for (String l: labels) { - PersistentEntity persistentEntity = findPersistentEntityWithLabel(l); - - int inheritenceChain = calcInheritenceChain(persistentEntity); - if (inheritenceChain > longestInheritenceChain) { - longestInheritenceChain = inheritenceChain; - result = persistentEntity; + PersistentEntity persistentEntity = findDerivedPersistentEntityWithLabel(pe, l); + if (persistentEntity!=null) { + int inheritenceChain = calcInheritenceChain(persistentEntity); + if (inheritenceChain > longestInheritenceChain) { + longestInheritenceChain = inheritenceChain; + result = persistentEntity; + } } } return result; } - private PersistentEntity findPersistentEntityWithLabel(String label) { + private PersistentEntity findDerivedPersistentEntityWithLabel(PersistentEntity parent, String label) { for (PersistentEntity pe: getMappingContext().getPersistentEntities()) { - if (((GraphPersistentEntity)pe).getLabels().contains(label)) { - return pe; + if (isInParentsChain(parent, pe)) { + if (((GraphPersistentEntity)pe).getLabels().contains(label)) { + return pe; + } } } - throw new IllegalStateException("no persistententity with discriminator " + label); + return null; } - int calcInheritenceChain(PersistentEntity pe) { - if (pe == null) { + private boolean isInParentsChain(PersistentEntity parent, PersistentEntity it) { + if (it==null) { + return false; + } else if (it.equals(parent)) { + return true; + } else return isInParentsChain(parent, it.getParentEntity()); + } + + private int calcInheritenceChain(PersistentEntity current) { + if (current == null) { return 0; } else { - return calcInheritenceChain(pe.getParentEntity()) + 1; + return calcInheritenceChain(current.getParentEntity()) + 1; } } @@ -132,43 +144,96 @@ entityAccess.setIdentifier(id); data.remove("__id__"); + Map<TypeDirectionPair, Map<String, Collection>> relationshipsMap = new HashMap<TypeDirectionPair, Map<String, Collection>>(); + CypherResult relationships = getSession().getNativeInterface().execute(String.format("MATCH (m%s {__id__:{1}})-[r]-(o) RETURN type(r) as relType, startNode(r)=m as out, {ids: collect(o.__id__), labels: collect(labels(o))} as values", ((GraphPersistentEntity)persistentEntity).getLabelsAsString()), Collections.singletonList(id)); + for (Map<String, Object> row : relationships) { + String relType = (String) row.get("relType"); + Boolean outGoing = (Boolean) row.get("out"); + Map<String, Collection> values = (Map<String, Collection>) row.get("values"); + TypeDirectionPair key = new TypeDirectionPair(relType, outGoing); + relationshipsMap.put(key, values); + } + for (PersistentProperty property: entityAccess.getPersistentEntity().getPersistentProperties()) { String propertyName = property.getName(); if (property instanceof Simple) { // implicitly sets version property as well entityAccess.setProperty(propertyName, data.remove(propertyName)); -// } else if (property instanceof OneToOne) { -// log.error("property " + property.getName() + " is of type " + property.getClass().getSuperclass()); - } else if (property instanceof ToOne) { - ToOne to = (ToOne) property; + } else if (property instanceof Association) { - CypherResult cypherResult = getSession().getNativeInterface().execute(CypherBuilder.findRelationshipEndpointIdsFor(to), Collections.singletonList(id)); - - Map<String,Object> row = IteratorUtil.singleOrNull(cypherResult); - if (row != null) { - Long endpointId = (Long) row.get("id"); - entityAccess.setProperty(propertyName, - getMappingContext().getProxyFactory().createProxy( - session, - to.getAssociatedEntity().getJavaClass(), - endpointId - ) - ); - } - } else if ((property instanceof OneToMany) || (property instanceof ManyToMany)) { - - LazyEnititySet lazyEnititySet = new LazyEnititySet( - entityAccess, - (Association) property, - getMappingContext().getProxyFactory(), - getSession() + Association association = (Association) property; + TypeDirectionPair typeDirectionPair = new TypeDirectionPair( + RelationshipUtils.relationshipTypeUsedFor(association), + !RelationshipUtils.useReversedMappingFor(association) ); - entityAccess.setProperty(propertyName, lazyEnititySet); + + Map<String, Collection> idsAndLabels = relationshipsMap.remove(typeDirectionPair); + Collection<Long> targetIds = idsAndLabels == null ? null : idsAndLabels.get("ids"); + + if (association instanceof ToOne) { + ToOne toOne = (ToOne) association; + if (targetIds!=null) { + Long targetId = IteratorUtil.single(targetIds); +// if (targetId!=null) { + entityAccess.setProperty(propertyName, + getMappingContext().getProxyFactory().createProxy( + session, + toOne.getAssociatedEntity().getJavaClass(), + targetId + ) + ); +// } + } + } else if ((association instanceof OneToMany) || (association instanceof ManyToMany)) { + Collection values = (Collection) entityAccess.getProperty(propertyName); + values = createDirtyCheckableAwareCollection(entityAccess, association, values); + entityAccess.setProperty(propertyName, values); + + if (targetIds!=null) { + for (Long targetId : targetIds) { + values.add(getMappingContext().getProxyFactory().createProxy( + session, + association.getAssociatedEntity().getJavaClass(), + targetId + ) + ); + + } + } + } else { + throw new IllegalArgumentException("association " + association.getName() + " is of type " + association.getClass().getSuperclass().getName()); + } } else { - throw new IllegalArgumentException("property $property.name is of type ${property.class.superclass}"); - } + throw new IllegalArgumentException("property " + property.getName() + " is of type " + property.getClass().getSuperclass().getName()); + } + } + + if (!relationshipsMap.isEmpty()) { + for (Map.Entry<TypeDirectionPair, Map<String,Collection>> entry: relationshipsMap.entrySet()) { + + if (entry.getKey().isOutgoing()) { + Iterator<Long> idIter = entry.getValue().get("ids").iterator(); + Iterator<Collection<String>> labelIter = entry.getValue().get("labels").iterator(); + + Collection values = new ArrayList(); + while (idIter.hasNext() && labelIter.hasNext()) { + Long targetId = idIter.next(); + Collection<String> labels = labelIter.next(); + Object proxy = getMappingContext().getProxyFactory().createProxy( + session, + ((Neo4jMappingContext) getMappingContext()).findPersistentEntityForLabels(labels).getJavaClass(), + targetId + ); + values.add(proxy); + } + + // for single instances and singular property name do not use an array + Object value = (values.size()==1) && isSingular(entry.getKey().getType()) ? IteratorUtil.single(values): values; + data.put(entry.getKey().getType(), value); + } + } } if (!data.isEmpty()) { @@ -176,10 +241,35 @@ go.setProperty(Neo4jGormEnhancer.UNDECLARED_PROPERTIES, data); } + firePostLoadEvent(entityAccess.getPersistentEntity(), entityAccess); return entityAccess.getEntity(); } + private Collection createCollection(Association association) { + return association.isList() ? new ArrayList() : new HashSet(); + } + + private Collection createDirtyCheckableAwareCollection(EntityAccess entityAccess, Association association, Collection delegate) { + if (delegate==null) { + delegate = createCollection(association); + } + if (!(delegate instanceof DirtyCheckableAwareCollection)) { + delegate = association.isList() ? + new DirtyCheckableAwareList(entityAccess, association, (List)delegate, getSession()) : + new DirtyCheckableAwareSet(entityAccess, association, (Set) delegate, getSession()); + } + return delegate; + } + + private boolean isSingular(String key) { + return PlingStemmer.isSingular(key); + } + + /*private Class<Object> findJavaClassForLabels(Object labels) { + return null; + }*/ + @Override protected Serializable persistEntity(PersistentEntity pe, Object obj) { if (obj == null) { @@ -259,17 +349,14 @@ } } - Iterable targets = (Iterable) propertyValue; + Collection targets = (Collection) propertyValue; persistEntities(association.getAssociatedEntity(), targets, persistingColl); boolean reversed = RelationshipUtils.useReversedMappingFor(association); if (!reversed) { - if (!(propertyValue instanceof LazyEnititySet)) { - LazyEnititySet les = new LazyEnititySet(entityAccess, association, getMappingContext().getProxyFactory(), getSession()); - les.addAll(targets); - entityAccess.setProperty(association.getName(), les); - } + Collection dcc = createDirtyCheckableAwareCollection(entityAccess, association, targets); + entityAccess.setProperty(association.getName(), dcc); } } } else if (pp instanceof ToOne) { @@ -298,12 +385,14 @@ String relType = RelationshipUtils.relationshipTypeUsedFor(to); if (!reversed) { + if (isUpdate) { + getSession().addPendingInsert(new RelationshipPendingDelete(entityAccess, relType, null , getCypherEngine())); + } getSession().addPendingInsert(new RelationshipPendingInsert(entityAccess, relType, new EntityAccess(to.getAssociatedEntity(), propertyValue), getCypherEngine())); } - } } else { throw new IllegalArgumentException("wtf don't know how to handle " + pp + "(" + pp.getClass() +")" ); @@ -361,30 +450,34 @@ // populate cascades for (Association association: pe.getAssociations()) { Object property = entityAccess.getProperty(association.getName()); - if (association.isOwningSide() && association.doesCascade(CascadeType.REMOVE) && (property!=null)) { - PersistentEntity associatedEntity = association.getAssociatedEntity(); + // TODO: check if property is an empty array -> exclude + if (association.isOwningSide() && association.doesCascade(CascadeType.REMOVE)) { - Collection<Object> cascadesForPersistentEntity = cascades.get(associatedEntity); - if (cascadesForPersistentEntity==null) { - cascadesForPersistentEntity = new ArrayList<Object>(); - cascades.put(associatedEntity, cascadesForPersistentEntity); + if (propertyNotEmpty(property)) { + + PersistentEntity associatedEntity = association.getAssociatedEntity(); + + Collection<Object> cascadesForPersistentEntity = cascades.get(associatedEntity); + if (cascadesForPersistentEntity==null) { + cascadesForPersistentEntity = new ArrayList<Object>(); + cascades.put(associatedEntity, cascadesForPersistentEntity); + } + + if (association instanceof ToOne) { + cascadesForPersistentEntity.add(property); + } else { + cascadesForPersistentEntity.addAll((Collection<?>) property); + } } - - if (association instanceof ToOne) { - cascadesForPersistentEntity.add(property); - } else { - cascadesForPersistentEntity.addAll((Collection<?>) property); - } - } } - } for (Map.Entry<PersistentEntity, Collection<Object>> entry: cascades.entrySet()) { - deleteEntities(entry.getKey(), entry.getValue()); - + if (!entry.getValue().isEmpty()) { + deleteEntities(entry.getKey(), entry.getValue()); + } } getCypherEngine().execute( @@ -396,6 +489,16 @@ } } + private boolean propertyNotEmpty(Object property) { + if (property==null) { + return false; + } + if ((property instanceof Collection) && ( ((Collection) property).isEmpty() )) { + return false; + } + return true; + } + @Override public Query createQuery() { return new Neo4jQuery(session, getPersistentEntity(), this);
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.java index bb173c8..af215ae 100644 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.java +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.java
@@ -15,13 +15,15 @@ package org.grails.datastore.gorm.neo4j; //import org.grails.datastore.gorm.neo4j.converters.*; -import org.grails.datastore.mapping.document.config.Attribute; +import org.grails.datastore.mapping.engine.NonPersistentTypeException; import org.grails.datastore.mapping.model.AbstractMappingContext; import org.grails.datastore.mapping.model.MappingConfigurationStrategy; import org.grails.datastore.mapping.model.MappingFactory; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy; +import java.util.Collection; + /** * @author Stefan Armbruster <stefan@armbruster-it.de> */ @@ -30,15 +32,9 @@ MappingFactory mappingFactory = new GraphGormMappingFactory(); MappingConfigurationStrategy mappingSyntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); -// Neo4jMappingContext() { -// mappingFactory = new GraphGormMappingFactory() -// syntaxStrategy = -// } - - public Neo4jMappingContext() { super(); - addTypeConverter(new LazyEntitySetToSetConverter()); +// addTypeConverter(new LazyEntitySetToSetConverter()); } @Override @@ -58,6 +54,18 @@ return persistentEntity; } + + public GraphPersistentEntity findPersistentEntityForLabels(Collection<String> labels) { + for (PersistentEntity pe : getPersistentEntities()) { + GraphPersistentEntity gpe = (GraphPersistentEntity) pe; + + if (gpe.getLabels().equals(labels)) { + return gpe; + } + } + throw new NonPersistentTypeException(labels.toString()); + } + // MappingFactory getMappingFactory() { // mappingFactory // }
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jSession.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jSession.java index 504e2bf..53d9681 100644 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jSession.java +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/Neo4jSession.java
@@ -77,7 +77,8 @@ if (pendingInsert instanceof NodePendingInsert) { nodes.add(pendingInsert); } - if (pendingInsert instanceof RelationshipPendingInsert) { + if ((pendingInsert instanceof RelationshipPendingInsert) || + (pendingInsert instanceof RelationshipPendingDelete)) { relationships.add(pendingInsert); }
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/NodePendingInsert.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/NodePendingInsert.java index 55c1786..d96b4fb 100644 --- a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/NodePendingInsert.java +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/NodePendingInsert.java
@@ -4,12 +4,11 @@ import org.grails.datastore.mapping.core.impl.PendingInsertAdapter; import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Simple; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Created by stefan on 15.02.14. @@ -40,12 +39,23 @@ } } - Neo4jGormEnhancer.amendMapWithUndeclaredProperties(simpleProps, getNativeEntry(), mappingContext); + Map<String, List<Object>> dynamicRelProps = Neo4jGormEnhancer.amendMapWithUndeclaredProperties(simpleProps, getNativeEntry(), mappingContext); String labels = ((GraphPersistentEntity)entity).getLabelsWithInheritance(getEntityAccess().getEntity()); String cypher = String.format("CREATE (n%s {1})", labels); cypherEngine.execute(cypher, Collections.singletonList(simpleProps)); + + for (Map.Entry<String, List<Object>> e: dynamicRelProps.entrySet()) { + for (Object o: e.getValue()) { + GraphPersistentEntity gpe = (GraphPersistentEntity)mappingContext.getPersistentEntity(o.getClass().getName()); + cypher = String.format("MATCH (a%s {__id__:{1}}), (b%s {__id__:{2}}) MERGE (a)-[:%s]->(b)", labels, gpe.getLabelsWithInheritance(o), e.getKey() ); + List params = new ArrayList(); + params.add(nativeKey); + params.add(new EntityAccess(gpe, o).getIdentifier()); + cypherEngine.execute(cypher, params); + } + } } } \ No newline at end of file
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/TypeDirectionPair.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/TypeDirectionPair.java new file mode 100644 index 0000000..b988030 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/TypeDirectionPair.java
@@ -0,0 +1,61 @@ +package org.grails.datastore.gorm.neo4j; + +import org.grails.datastore.mapping.model.types.Association; + +/** + * combination of relationship type and direction to be used a key in a map + */ +public class TypeDirectionPair { + + private String type; + private boolean outgoing; + + public TypeDirectionPair(String type, boolean outgoing) { + this.type = type; + this.outgoing = outgoing; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isOutgoing() { + return outgoing; + } + + public void setOutgoing(boolean outgoing) { + this.outgoing = outgoing; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TypeDirectionPair that = (TypeDirectionPair) o; + + if (outgoing != that.outgoing) return false; + if (!type.equals(that.type)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + (outgoing ? 1 : 0); + return result; + } + + @Override + public String toString() { + return "TypeDirectionPair{" + + "type='" + type + '\'' + + ", outgoing=" + outgoing + + '}'; + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalMap.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalMap.java new file mode 100644 index 0000000..657cc29 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalMap.java
@@ -0,0 +1,43 @@ +package org.grails.datastore.gorm.neo4j.datatypes; +import java.util.TreeMap; + +/** +This class is part of the Java Tools (see http://mpii.de/yago-naga/javatools). +It is licensed under the Creative Commons Attribution License +(see http://creativecommons.org/licenses/by/3.0) by +the YAGO-NAGA team (see http://mpii.de/yago-naga). + + + + + +Provides a nicer constructor for a TreeMap. +Example: +<PRE> + FinalMap<String,Integer> f=new FinalMap( + "a",1, + "b",2, + "c",3); + System.out.println(f.get("b")); + --> 2 +</PRE> +*/ +public class FinalMap<T1 extends Comparable,T2> extends TreeMap<T1,T2>{ + private static final long serialVersionUID = 1L; + +/** Constructs a FinalMap from an array that contains key/value sequences */ + @SuppressWarnings("unchecked") + public FinalMap(Object... a) { + super(); + for(int i=0;i<a.length-1;i+=2) { + if(containsKey((T1)a[i])) throw new RuntimeException("Duplicate key in FinalMap: "+a[i]); + put((T1)a[i],(T2)a[i+1]); + } + } + + /** Test routine */ + public static void main(String[] args) { + FinalMap<String,Integer> f=new FinalMap<String,Integer>("a",1,"b",2); + System.out.println(f.get("b")); + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalSet.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalSet.java new file mode 100644 index 0000000..fda8927 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/datatypes/FinalSet.java
@@ -0,0 +1,73 @@ +package org.grails.datastore.gorm.neo4j.datatypes; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Set; + +import org.grails.datastore.gorm.neo4j.javatools.administrative.D; +/** +This class is part of the Java Tools (see http://mpii.de/yago-naga/javatools). +It is licensed under the Creative Commons Attribution License +(see http://creativecommons.org/licenses/by/3.0) by +the YAGO-NAGA team (see http://mpii.de/yago-naga). + + + + + +This class provides a very simple container implementation with zero overhead. +A FinalSet bases on a sorted, unmodifiable array. The constructor +can either be called with a sorted unmodifiable array (default constructor) +or with an array that can be cloned and sorted beforehand if desired. +Example: +<PRE> + FinalSet<String> f=new FinalSet("a","b","c"); + // equivalently: + // FinalSet<String> f=new FinalSet(new String[]{"a","b","c"}); + // FinalSet<String> f=new FinalSet(SHALLNOTBECLONED,ISSORTED,"a","b","c"); + System.out.println(f.get(1)); + --> b +</PRE> +*/ +public class FinalSet<T extends Comparable<?>> extends AbstractList<T> implements Set<T>{ + /** Holds the data, must be sorted */ + public T[] data; + /** Constructs a FinalSet from an array, clones and sorts the array if indicated. */ + @SuppressWarnings("unchecked") + public FinalSet(boolean clone,T... a) { + if(clone) { + Comparable<?>[] b=new Comparable[a.length]; + System.arraycopy(a,0,b,0,a.length); + a=(T[])b; + } + Arrays.sort(a); + data=a; + } + /** Constructs a FinalSet from an array that does not need to be cloned */ + public FinalSet(T... a) { + this(false,a); + } + /** Tells whether x is in the container */ + public boolean contains(T x) { + return(Arrays.binarySearch(data,x)>=0); + } + /** Returns the position in the array or -1 */ + public int indexOf(T x) { + int r=Arrays.binarySearch(data,x); + return(r>=0?r:-1); + } + /** Returns the element at position i*/ + public T get(int i) { + return(data[i]); + } + + /** Returns the number of elements in this FinalSet */ + public int size() { + return(data.length); + } + + /** Test routine */ + public static void main(String[] args) { + FinalSet<String> f=new FinalSet<String>("b","a","c"); + D.p(f.get(1)); + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/javatools/administrative/D.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/javatools/administrative/D.java new file mode 100644 index 0000000..fea709a --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/javatools/administrative/D.java
@@ -0,0 +1,423 @@ +package org.grails.datastore.gorm.neo4j.javatools.administrative; + +import org.grails.datastore.gorm.neo4j.parsers.Char; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +/** + This class is part of the Java Tools (see http://mpii.de/yago-naga/javatools). + It is licensed under the Creative Commons Attribution License + (see http://creativecommons.org/licenses/by/3.0) by + the YAGO-NAGA team (see http://mpii.de/yago-naga). + + + + + + This class provides convenience methods for Input/Output. + Allows to do basic I/O with easy procedure calls + -- nearly like in normal programming languages. + Furthermore, the class provides basic set operations for EnumSets, NULL-safe + comparisons and adding to maps.<BR> + Example: + <PRE> + D.p("This is an easy way to write a string"); + // And this is an easy way to read one: + String s=D.r(); + + // Here is a cool way to print something inline + computeProduct(factor1,(Integer)D.p(factor2)); + + // Here are some tricks with enums + enum T {a,b,c}; + EnumSet<T> i=D.intersection(EnumSet.of(T.a,T.b),EnumSet.of(T.b,T.c)); + EnumSet<T> u=D.union(EnumSet.of(T.a,T.b),EnumSet.of(T.b,T.c)); + + // Here is how to compare things, even if they are NULL + D.compare(object1, object2); + + // Here is how to add something to maps that contain lists + Map<String,List<String>> string2list=new TreeMap<String,List<String>>(); + D.addKeyValue(string2list,"key","new list element",ArrayList.class); + // now, the map contains "key" -> [ "new list element" ] + D.addKeyValue(string2list,"key","again a new list element",ArrayList.class); + // now, the map contains "key" -> [ "new list element", "again a new list element" ] + + // Here is how to add something to maps that contain integers + Map<String,Integer> string2list=new TreeMap<String,Integer>(); + D.addKeyValue(string2list,"key",7); // map now contains "key" -> 7 + D.addKeyValue(string2list,"key",3); // map now contains "key" -> 10 + + </PRE> + */ +public class D { + + /** Indentation margin. All methods indent their output by indent spaces */ + public static int indent = 0; + + /** Prints <indent> spaces */ + protected static void i() { + for (int i = 0; i < indent; i++) + System.out.print(" "); + } + + /** Prints some Objects, returns them */ + public static Object p(Object... a) { + pl(a); + System.out.println(""); + if (a == null || a.length == 0) return (null); + if (a.length == 1) return (a[0]); + return (a); + } + + /** Prints some Objects */ + public static Object println(Object... a) { + return (p(a)); + } + + /** Prints some Objects on one line */ + public static void pl(Object... a) { + System.out.print(toString(a)); + } + + /** Prints an array of integers*/ + public static int[] p(int[] a) { + i(); + if (a == null) System.out.print("null-array"); + else for (int i = 0; i < a.length; i++) + System.out.print(a[i] + ", "); + System.out.println(""); + return (a); + } + + /** Prints an array of doubles*/ + public static double[] p(double[] a) { + i(); + if (a == null) System.out.print("null-array"); + else for (int i = 0; i < a.length; i++) + System.out.print(a[i] + ", "); + System.out.println(""); + return (a); + } + + /** Reads a line from the keyboard */ + public static String r() { + String s = ""; + i(); + try { + s = new BufferedReader(new InputStreamReader(System.in)).readLine(); + } catch (Exception whocares) { + } + return (s); + } + + /** Reads a line from the keyboard */ + public static String read() { + return (r()); + } + + /** Reads a long from the keyboard */ + public static String read(String question) { + System.out.print(question+" "); + return (D.read()); + } + + /** Reads a long from the keyboard */ + public static boolean readBoolean(String question) { + System.out.print(question+" "); + return (D.read().startsWith("y")); + } + + /** Reads a long from the keyboard */ + public static long readLong(String question) { + System.out.print(question); + return (Long.parseLong(D.r())); + } + + /** Reads a double from the keyboard */ + public static double readDouble(String question) { + System.out.print(question); + return (Double.parseDouble(D.r())); + } + + /** Waits for a number of milliseconds */ + public static void waitMS(long milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException ex) { + } + } + + /** Returns the intersection of two enumsets */ + public static <E extends Enum<E>> EnumSet<E> intersection(EnumSet<E> s1, EnumSet<E> s2) { + // We have to clone, since retainAll modifies the set + EnumSet<E> s = s1.clone(); + s.retainAll(s2); + // I tried coding this for arbitrary sets, but it failed because + // the interface Cloneable does not make sure that the clone-method + // is visible (!) + return (s); + } + + /** Returns the union of two enumsets */ + public static <E extends Enum<E>> EnumSet<E> union(EnumSet<E> s1, EnumSet<E> s2) { + EnumSet<E> s = s1.clone(); + s.addAll(s2); + return (s); + } + + /** Tells whether the intersection is non-empty */ + public static <E extends Enum<E>> boolean containsOneOf(EnumSet<E> s1, EnumSet<E> s2) { + return (!intersection(s1, s2).isEmpty()); + } + + /** Exits with error code 0 */ + public static void exit() { + System.exit(0); + } + + /** Writes a line to a writer. Yes, this is possible */ + public static void writeln(Writer out, Object s) throws IOException { + out.write(s.toString()); + out.write("\n"); + } + + /** Writes a line to a writer. Yes, this is possible */ + public static void writeln(OutputStream out, Object s) throws IOException { + String string = Char.encodeUTF8(s.toString()); + for (int i = 0; i < string.length(); i++) + out.write(string.charAt(i)); + out.write('\n'); + } + + /** Writes a line silently to a writer. */ + public static void silentWriteln(Writer out, Object s) { + try { + out.write(s.toString()); + out.write("\n"); + } catch (Exception e) { + } + } + + /** Executes a command */ + public static void execute(String cmd, File folder) throws Exception { + Process p = Runtime.getRuntime().exec(cmd, null, folder); + BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream())); + BufferedReader bre = new BufferedReader(new InputStreamReader(p.getErrorStream())); + String s1, s2 = null; + while (null != (s1 = bri.readLine()) || null != (s2 = bre.readLine())) { + if (s1 != null) System.out.println(s1); + if (s2 != null) System.err.println(s2); + } + p.waitFor(); + } + + /** Given a map that maps to collections, adds a new key/value pair or introduces the key*/ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static <K, V, C extends Collection<V>, L extends Collection> void addKeyValue(Map<K, C> map, K key, V value, Class<L> collectionType) { + C coll = map.get(key); + if (coll == null) { + try { + map.put(key, coll = (C) collectionType.newInstance()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + coll.add(value); + } + + /** Given a map that maps to collections, adds a new key/value pair or introduces the key*/ + @SuppressWarnings({ "rawtypes" }) + public static <K, V, C extends Collection<V>, L extends Collection> void addKeyValues(Map<K, C> map, K key, C values, Class<L> collectionType) { + for(V val : values) addKeyValue(map,key,val,collectionType); + } + + /** Given a map that maps to integers, adds a new key/value pair or increases the counter*/ + public static <K> void addKeyValue(Map<K, Integer> map, K key, int value) { + Integer coll = map.get(key); + if (coll == null) { + map.put(key, value); + return; + + } + map.put(key, coll + value); + } + + /** Given a map that maps to floats, adds a new key/value pair or increases the counter*/ + public static <K> void addKeyValueFlt(Map<K, Float> map, K key, float value) { + Float coll = map.get(key); + if (coll == null) { + map.put(key, value); + return; + } + map.put(key, coll + value); + } + + /** Given a map that maps to doubles, adds a new key/value pair or increases the counter*/ + public static <K> void addKeyValueDbl(Map<K, Double> map, K key, double value) { + Double coll = map.get(key); + if (coll == null) { + map.put(key, value); + return; + + } + map.put(key, coll + value); + } + + /** Given a map that maps to comparable objects, sets a key to a given value iff the current value is null or smaller than the given value*/ + public static <K ,V extends Comparable<V>> void setKeyValueIfGreaterThanCurrent(Map<K, V> map, K key, V value) { + V coll = map.get(key); + if (coll == null) { + map.put(key, value); + return; + } + if(coll.compareTo(value)<0) + map.put(key, value); + } + + + /** Returns the element of a map or 0*/ + public static <K> int getOrZero(Map<K, Integer> map, K key) { + Integer i = map.get(key); + if (i == null) return (0); + return (i); + } + + /** Returns the element of a map or 0*/ + public static <K> double getOrZeroDouble(Map<K, Double> map, K key) { + Double i = map.get(key); + if (i == null) return (0); + return (i); + } + + /** Returns the element of a map or a default value*/ + public static <K,V> V getOr(Map<K, V> map, K key, V defValue) { + V i = map.get(key); + if (i == null) return defValue; + return (i); + } + + /** Returns a sorted list of the items*/ + public static<T> List<T> sorted(final Map<T, Integer> map) { + List<T> list=new ArrayList<T>(map.keySet()); + Collections.sort(list,new Comparator<T>(){ + + @Override + public int compare(T arg0, T arg1) { + return (map.get(arg1).compareTo(map.get(arg0))); + }}); + return(list); + } + + /** Returns a sorted list of the items*/ + public static<T> List<T> sortedDouble(final Map<T, Double> map) { + List<T> list=new ArrayList<T>(map.keySet()); + Collections.sort(list,new Comparator<T>(){ + + @Override + public int compare(T arg0, T arg1) { + return (map.get(arg1).compareTo(map.get(arg0))); + }}); + return(list); + } + + /** Returns true if two things are equal, including NULL */ + public static <E> boolean equal(E s1, E s2) { + if (s1 == s2) return (true); + if (s1 == null) return (false); + if (s2 == null) return (false); + return (s1.equals(s2)); + } + + /** Compares two things, including NULL */ + public static <E extends Comparable<E>> int compare(E s1, E s2) { + if (s1 == s2) return (0); + if (s1 == null) return (-1); + if (s2 == null) return (1); + return (s1.compareTo(s2)); + } + + /** Compares pairs of comparable things (a1,a2,b1,b2,...), including NULL */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static int comparePairs(Object... o) { + for (int i = 0; i < o.length; i += 2) { + int c = compare((Comparable) o[i], (Comparable) o[i + 1]); + if (c != 0) return (c); + } + return (0); + } + + /** Compares pairs of comparable things (a1,a2,b1,b2,...) for equality, including NULL */ + public static boolean equalPairs(Object... o) { + for (int i = 0; i < o.length; i += 2) { + if (!equal(o[i], o[i + 1])) return (false); + } + return (true); + } + + /** Returns the index of a thing in an array or -1*/ + public static int indexOf(Object o, Object... os) { + for (int i = 0; i < os.length; i++) { + if (D.equal(os[i], o)) return (i); + } + return (-1); + } + + /** TRUE if the first enum is before the second*/ + public static <C extends Enum<C>> boolean smaller(Enum<C> e1, Enum<C> e2) { + return (e1.ordinal() < e2.ordinal()); + } + + /** Returns a reasonable String representation of a sequence of things. Handles arrays, deep arrays and NULL.*/ + public static String toString(Object... o) { + if (o == null) { + return ("null"); + } + StringBuilder b = new StringBuilder(); + for (int i = 0; i < o.length; i++) { + if (o[i] == null) { + b.append("null"); + continue; + } + if (o[i].getClass().isArray()) { + b.append("["); + if (((Object[]) o[i]).length != 0) { + for (Object obj : (Object[]) o[i]) { + b.append(toString(obj)).append(", "); + } + } + b.append("]"); + } else { + b.append(o[i].toString()); + } + if (i != o.length - 1) b.append(" "); + } + return (b.toString()); + } + + /** Picks one element from a set or NULL*/ + public static <T> T pick(Collection<T> set) { + if(set==null || set.isEmpty()) return(null); + return(set.iterator().next()); + } + + /** Returns the size of the intersection*/ + public static<T> int intersectionSize(Collection<T> c1, Collection<T> c2) { + if(c1.size()>c2.size()) return(intersectionSize(c2,c1)); + int result=0; + for(T t : c1) if(c2.contains(t)) result++; + return(result); + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/Char.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/Char.java new file mode 100644 index 0000000..8a5e5b9 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/Char.java
@@ -0,0 +1,1436 @@ +package org.grails.datastore.gorm.neo4j.parsers; + +import org.grails.datastore.gorm.neo4j.datatypes.FinalMap; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.TreeMap; + + +/** +This class is part of the Java Tools (see http://mpii.de/yago-naga/javatools). +It is licensed under the Creative Commons Attribution License +(see http://creativecommons.org/licenses/by/3.0) by +the YAGO-NAGA team (see http://mpii.de/yago-naga). + + + + + This class provides static methods to <I>decode, encode</I> and <I>normalize</I> Strings.<BR> + <B>Decoding</B> converts the following codes to Java 16-bit characters (<TT>char</TT>): + <UL> + <LI>all HTML ampersand codes (like &nbsp;) as specified by the W3C + <LI>all backslash codes (like \ b) as specified by the Java language specification + <LI>all percentage codes (like %2C) as used in URLs and E-Mails + <LI>all UTF-8 codes (like Ä«) as specified in Wikipedia + </UL> + <P> + <B>Encoding</B> is the inverse operation. It takes a Java 16-bit character (<TT>char</TT>) and + outputs its encoding in HTML, as a backslash code, as a percentage code or in UTF8. + <P> + <B>Normalization</B> converts the following Unicode characters (Java 16-bit <TT>char</TT>s) + to ASCII-characters in the range 0x20-0x7F: + <UL> + <LI>all ASCII control characters (0x00-0x1F) + <LI>all Latin-1 characters (0x80-0xFF) to the closest transliteration + <LI>all Latin Extended-A characters (0x100-0x17F) to the closest transliteration + <LI>all Greek characters (0x374-0x3D6) to the closest transliteration as specified in Wikipedia + <LI>all General-Punctuation characters (0x2016-0x2055) to the closest ASCII punctuation + <LI>most mathematical symbols (in the range of 0x2000) to the common program code identifier or text + <LI>all ligatures (0xFB00-0xFB06, the nasty things you get when you copy/paste from PDFs) to + the separate characters + </UL> + <P> + <CENTER><H3>Usage</H3></CENTER> + <P> + <B>Decoding</B> is done by methods that "eat" a code from the string. + They require as an additional parameter an integer array of length 1, + in which they store the length of the code that they chopped off.<BR> + Example: + <PRE> + int[] eatLength=new int[1]; + char c=eatPercentage("%2Cblah blah",eatLength); + --> c=',' + eatLength[0]=3 // the code was 3 characters long + </PRE> + There is a static integer array Char.eatLength, which you can use for this purpose. + The methods store 0 in case the String does not start with the correct code. + They store -1 in case the String starts with a corrupted code. Of course, you can + use the <TT>eat...</TT> methods also to decode one single code. There are methods + <TT>decode...</TT> that decode the percentage code, the UTF8-codes, the backslash codes + or the Ampersand codes, respectively. + The method <TT>decode(String)</TT> decodes all codes of a String.<BR> + Example: + <PRE> + decode("This String contains some codes: &amp; %2C \ u0041"); + --> "This String contains some codes: & , A" + </PRE> + <P> + <B>Normalization</B> is done by the method <TT>normalize(int c)</TT>. It converts a Unicode + character (a 16-bit Java character <TT>char</TT>) + to a sequence of normal characters (i.e. characters in the range 0x20-0x7F). + The transliteration may consist of multiple chars (e.g. for umlauts) and also of no + chars at all (e.g. for Unicode Zero-Space-Characters). <BR> + Example: + <PRE> + normalize('ä'); + --> "ae" + </PRE> + The method <TT>normalize(String)</TT> normalizes all characters in a String.<BR> + Example: + <PRE> + normalize("This String contains the umlauts �, � and �"); + --> "This String contains the umlauts Ae, Oe and Ue" + </PRE> + If the method cannot find a normalization, it calls defaultNormalizer.apply(char c). + Decoding and normalizing can be combined by the method decodeAndNormalize(String s). + <P> + <B>Encoding</B> is done by methods called <TT>encode...(char)</TT>. These methods take a character + and transform it to a UTF8 code, a percentage code, an ampersand code or a backslash code, + respectively. If the character is normal (i.e. in the range 0x20-0x7F), they simply return the input + character without any change.<BR> + Example: + <PRE> + encodePercentage('�'); + --> "%C4" + </PRE> + There are also methods that work on entire Strings<BR> + Example: + <PRE> + encodePercentage("This String contains the umlauts �, � and �"); + --> "This String contains the umlauts %C4, %D6 and %DC;" + </PRE> + <P> + Last, this class provides the character categorization for URIs, as given in + http://tools.ietf.org/html/rfc3986 . It also provides a method to encode only those + characters that are not valid path component characters<BR> + Example: + <PRE> + isReserved(';'); + --> true + encodeURIPathComponent("a: b") + --> "a:%20b" + </PRE> + */ +public class Char { + + /** Defines just one function from an int to a String */ + public interface Char2StringFn { + + /** Function from a char to a String */ + String apply(char c); + } + + /** Called by normalize(int) in case the character cannot be normalized. + * The default implementation returns UNKNOWN. + * Feel free to create a new Char2StringFn and assign it to defaultNormalizer. */ + public static Char2StringFn defaultNormalizer = new Char2StringFn() { + + public String apply(char c) { + return (UNKNOWN); + } + }; + + /** String returned by the default implementation of defaultNormalizer, "[?]"*/ + public static String UNKNOWN = "[?]"; + + /** Maps a special character to a HTML ampersand sequence */ + public static Map<Character, String> charToAmpersand = new FinalMap<Character, String>('&', "&", '\'', "'", '<', "<", '>', ">", '"', """); + + /** Maps a special character to a backslash sequence */ + public static Map<Character, String> charToBackslash= new FinalMap<Character, String>('\\', "\\\\", '\n', "\\n"); + + /** Maps HTML ampersand sequences to strings */ + public static Map<String, Character> ampersandMap = new FinalMap<String, Character>("nbsp", (char) 160, "iexcl", (char) 161, "cent", (char) 162, "pound", (char) 163, "curren", (char) 164, "yen", (char) 165, "brvbar", (char) 166, "sect", + (char) 167, "uml", (char) 168, "copy", (char) 169, "ordf", (char) 170, "laquo", (char) 171, "not", (char) 172, "shy", (char) 173, "reg", (char) 174, "macr", (char) 175, "deg", (char) 176, "plusmn", (char) 177, "sup2", (char) 178, "sup3", + (char) 179, "acute", (char) 180, "micro", (char) 181, "para", (char) 182, "middot", (char) 183, "cedil", (char) 184, "sup1", (char) 185, "ordm", (char) 186, "raquo", (char) 187, "frac14", (char) 188, "frac12", (char) 189, "frac34", (char) 190, + "iquest", (char) 191, "Agrave", (char) 192, "Aacute", (char) 193, "Acirc", (char) 194, "Atilde", (char) 195, "Auml", (char) 196, "Aring", (char) 197, "AElig", (char) 198, "Ccedil", (char) 199, "Egrave", (char) 200, "Eacute", (char) 201, + "Ecirc", (char) 202, "Euml", (char) 203, "Igrave", (char) 204, "Iacute", (char) 205, "Icirc", (char) 206, "Iuml", (char) 207, "ETH", (char) 208, "Ntilde", (char) 209, "Ograve", (char) 210, "Oacute", (char) 211, "Ocirc", (char) 212, "Otilde", + (char) 213, "Ouml", (char) 214, "times", (char) 215, "Oslash", (char) 216, "Ugrave", (char) 217, "Uacute", (char) 218, "Ucirc", (char) 219, "Uuml", (char) 220, "Yacute", (char) 221, "THORN", (char) 222, "szlig", (char) 223, "agrave", + (char) 224, "aacute", (char) 225, "acirc", (char) 226, "atilde", (char) 227, "auml", (char) 228, "aring", (char) 229, "aelig", (char) 230, "ccedil", (char) 231, "egrave", (char) 232, "eacute", (char) 233, "ecirc", (char) 234, "euml", + (char) 235, "igrave", (char) 236, "iacute", (char) 237, "icirc", (char) 238, "iuml", (char) 239, "eth", (char) 240, "ntilde", (char) 241, "ograve", (char) 242, "oacute", (char) 243, "ocirc", (char) 244, "otilde", (char) 245, "ouml", + (char) 246, "divide", (char) 247, "oslash", (char) 248, "ugrave", (char) 249, "uacute", (char) 250, "ucirc", (char) 251, "uuml", (char) 252, "yacute", (char) 253, "thorn", (char) 254, "yuml", (char) 255, "fnof", (char) 402, "Alpha", + (char) 913, "Beta", (char) 914, "Gamma", (char) 915, "Delta", (char) 916, "Epsilon", (char) 917, "Zeta", (char) 918, "Eta", (char) 919, "Theta", (char) 920, "Iota", (char) 921, "Kappa", (char) 922, "Lambda", (char) 923, "Mu", (char) 924, "Nu", + (char) 925, "Xi", (char) 926, "Omicron", (char) 927, "Pi", (char) 928, "Rho", (char) 929, "Sigma", (char) 931, "Tau", (char) 932, "Upsilon", (char) 933, "Phi", (char) 934, "Chi", (char) 935, "Psi", (char) 936, "Omega", (char) 937, "alpha", + (char) 945, "beta", (char) 946, "gamma", (char) 947, "delta", (char) 948, "epsilon", (char) 949, "zeta", (char) 950, "eta", (char) 951, "theta", (char) 952, "iota", (char) 953, "kappa", (char) 954, "lambda", (char) 955, "mu", (char) 956, "nu", + (char) 957, "xi", (char) 958, "omicron", (char) 959, "pi", (char) 960, "rho", (char) 961, "sigmaf", (char) 962, "sigma", (char) 963, "tau", (char) 964, "upsilon", (char) 965, "phi", (char) 966, "chi", (char) 967, "psi", (char) 968, "omega", + (char) 969, "thetasym", (char) 977, "upsih", (char) 978, "piv", (char) 982, "bull", (char) 8226, "hellip", (char) 8230, "prime", (char) 8242, "Prime", (char) 8243, "oline", (char) 8254, "frasl", (char) 8260, "weierp", (char) 8472, "image", + (char) 8465, "real", (char) 8476, "trade", (char) 8482, "alefsym", (char) 8501, "larr", (char) 8592, "uarr", (char) 8593, "rarr", (char) 8594, "darr", (char) 8595, "harr", (char) 8596, "crarr", (char) 8629, "lArr", (char) 8656, "uArr", + (char) 8657, "rArr", (char) 8658, "dArr", (char) 8659, "hArr", (char) 8660, "forall", (char) 8704, "part", (char) 8706, "exist", (char) 8707, "empty", (char) 8709, "nabla", (char) 8711, "isin", (char) 8712, "notin", (char) 8713, "ni", + (char) 8715, "prod", (char) 8719, "sum", (char) 8721, "minus", (char) 8722, "lowast", (char) 8727, "radic", (char) 8730, "prop", (char) 8733, "infin", (char) 8734, "ang", (char) 8736, "and", (char) 8743, "or", (char) 8744, "cap", (char) 8745, + "cup", (char) 8746, "int", (char) 8747, "there4", (char) 8756, "sim", (char) 8764, "cong", (char) 8773, "asymp", (char) 8776, "ne", (char) 8800, "equiv", (char) 8801, "le", (char) 8804, "ge", (char) 8805, "sub", (char) 8834, "sup", + (char) 8835, "nsub", (char) 8836, "sube", (char) 8838, "supe", (char) 8839, "oplus", (char) 8853, "otimes", (char) 8855, "perp", (char) 8869, "sdot", (char) 8901, "lceil", (char) 8968, "rceil", (char) 8969, "lfloor", (char) 8970, "rfloor", + (char) 8971, "lang", (char) 9001, "rang", (char) 9002, "loz", (char) 9674, "spades", (char) 9824, "clubs", (char) 9827, "hearts", (char) 9829, "diams", (char) 9830, "quot", (char) 34, "amp", (char) 38, "lt", (char) 60, "gt", (char) 62, + "OElig", (char) 338, "oelig", (char) 339, "Scaron", (char) 352, "scaron", (char) 353, "Yuml", (char) 376, "circ", (char) 710, "tilde", (char) 732, "ensp", (char) 8194, "emsp", (char) 8195, "thinsp", (char) 8201, "zwnj", (char) 8204, "zwj", + (char) 8205, "lrm", (char) 8206, "rlm", (char) 8207, "ndash", + (char) 8211, //0x2013 + "mdash", (char) 8212, "lsquo", (char) 8216, "rsquo", (char) 8217, "sbquo", (char) 8218, "ldquo", (char) 8220, "rdquo", (char) 8221, "bdquo", (char) 8222, "dagger", (char) 8224, "Dagger", (char) 8225, "permil", (char) 8240, "lsaquo", + (char) 8249, "rsaquo", (char) 8250, "euro", (char) 8364, "apos", '\''); + + /** Maps characters to normalizations */ + public static Map<Character, String> normalizeMap = new TreeMap<Character, String>(); + static { + Object[] o = new Object[] { + // ASCII + (char) 7, + "BEEP", + (char) 9, + " ", + (char) 10, + "\n", + + // Latin-1 + (char) 160, + " ", + (char) 161, + "!", + (char) 162, + "cent", + (char) 163, + "pound", + (char) 164, + "currency", + (char) 165, + "yen", + (char) 166, + "|", + (char) 167, + "/", + (char) 169, + "(c)", + (char) 170, + "^a", + (char) 171, + "\"", + (char) 172, + "~", + (char) 173, + "", + (char) 174, + "(R)", + (char) 176, + "degree", + (char) 177, + "+/-", + (char) 178, + "^2", + (char) 179, + "^3", + (char) 180, + "'", + (char) 181, + "mu", + (char) 182, + "P", + (char) 183, + ".", + (char) 184, + ",", + (char) 185, + "^1", + (char) 186, + "^o", + (char) 187, + "\"", + (char) 188, + "1/4", + (char) 189, + "1/2", + (char) 190, + "3/4", + (char) 191, + "?", + (char) 0xC4, + "Ae", + (char) 0xD6, + "Oe", + (char) 0xDC, + "Ue", + (char) 0xDF, + "ss", + (char) 0xC6, + "Ae", + (char) 0xC7, + "C", + (char) 0xD0, + "D", + (char) 0xD1, + "N", + (char) 0xD7, + "x", + (char) 0xDD, + "Y", + (char) 0xDE, + "b", + (char) 0xF7, + "/", + (char) 0xFF, + "y", + + // Latin Extended-A + (char) 0x132, + "IJ", + (char) 0x134, + "J", + (char) 0x170, + "Ue", + (char) 0x174, + "W", + (char) 0x17F, + "f", + + // Greek + (char) 0x374, + "'", + (char) 0x375, + ",", + (char) 0x37A, + ",", + (char) 0x37E, + ";", + (char) 0x384, + "'", + (char) 0x385, + "'", + (char) 0x386, + "A", + (char) 0x387, + ".", + (char) 0x388, + "E", + (char) 0x380, + "I", + (char) 0x38C, + "O", + (char) 0x38E, + "Y", + (char) 0x38F, + "O", + (char) 0x390, + "i", + (char) 215, + "*", + (char) 913, + "A", + (char) 914, + "B", + (char) 915, + "G", + (char) 916, + "D", + (char) 917, + "E", + (char) 918, + "Z", + (char) 919, + "E", + (char) 920, + "Th", + (char) 921, + "I", + (char) 922, + "K", + (char) 923, + "L", + (char) 924, + "M", + (char) 925, + "N", + (char) 926, + "X", + (char) 927, + "O", + (char) 928, + "P", + (char) 929, + "R", + (char) 931, + "S", + (char) 932, + "T", + (char) 933, + "Y", + (char) 934, + "Ph", + (char) 935, + "Ch", + (char) 936, + "Ps", + (char) 937, + "O", + (char) 977, + "th", + (char) 978, + "y", + (char) 982, + "pi", + + // General Punctuation + (char) 0x2013, + "-", + (char) 0x2016, + "||", + (char) 0x2017, + "_", + (char) 0x2020, + "+", + (char) 0x2021, + "++", + (char) 0x2022, + "*", + (char) 0x2023, + "*", + (char) 0x2024, + ".", + (char) 0x2025, + "..", + (char) 0x2026, + "...", + (char) 0x2027, + ".", + (char) 0x2028, + "\n", + (char) 0x2030, + "/1000", + (char) 0x2031, + "/10000", + (char) 0x2032, + "'", + (char) 0x2033, + "''", + (char) 0x2034, + "'''", + (char) 0x2035, + "'", + (char) 0x2036, + "''", + (char) 0x2037, + "'''", + (char) 0x2038, + "^", + (char) 0x2039, + "\"", + (char) 0x203A, + "\"", + (char) 0x203B, + "*", + (char) 0x203C, + "!!", + (char) 0x203D, + "?!", + (char) 0x2041, + ",", + (char) 0x2042, + "***", + (char) 0x2043, + "-", + (char) 0x2044, + "/", + (char) 0x2045, + "[", + (char) 0x2046, + "]", + (char) 0x2047, + "??", + (char) 0x2048, + "?!", + (char) 0x2049, + "!?", + (char) 0x204A, + "-", + (char) 0x204B, + "P", + (char) 0x204C, + "<", + (char) 0x204D, + ">", + (char) 0x204F, + ";", + (char) 0x2050, + "-", + (char) 0x2051, + "**", + (char) 0x2052, + "./.", + (char) 0x2053, + "~", + (char) 0x2054, + "_", + (char) 0x2055, + "_", + + // Mathematical symbols + (char) 8465, + "I", + (char) 8476, + "R", + (char) 8482, + "(TM)", + (char) 8501, + "a", + (char) 8592, + "<-", + (char) 8593, + "^", + (char) 8594, + "->", + (char) 8595, + "v", + (char) 8596, + "<->", + (char) 8629, + "<-'", + (char) 8656, + "<=", + (char) 8657, + "^", + (char) 8658, + "=>", + (char) 8659, + "v", + (char) 8660, + "<=>", + (char) 8704, + "FOR ALL", + (char) 8706, + "d", + (char) 8707, + "EXIST", + (char) 8709, + "{}", + (char) 8712, + "IN", + (char) 8713, + "NOT IN", + (char) 8715, + "CONTAINS", + (char) 8719, + "PRODUCT", + (char) 8721, + "SUM", + (char) 8722, + "-", + (char) 8727, + "*", + (char) 8730, + "SQRT", + (char) 8733, + "~", + (char) 8734, + "INF", + (char) 8736, + "angle", + (char) 8743, + "&", + (char) 8744, + "|", + (char) 8745, + "INTERSECTION", + (char) 8746, + "UNION", + (char) 8747, + "INTEGRAL", + (char) 8756, + "=>", + (char) 8764, + "~", + (char) 8773, + "~=", + (char) 8776, + "~=", + (char) 8800, + "!=", + (char) 8801, + "==", + (char) 8804, + "=<", + (char) 8805, + ">=", + (char) 8834, + "SUBSET OF", + (char) 8835, + "SUPERSET OF", + (char) 8836, + "NOT SUBSET OF", + (char) 8838, + "SUBSET OR EQUAL", + (char) 8839, + "SUPERSET OR EQUAL", + (char) 8853, + "(+)", + (char) 8855, + "(*)", + (char) 8869, + "_|_", + (char) 8901, + "*", + (char) 8364, + "EUR", + + // Ligatures + (char) 0xFB00, + "ff", + (char) 0xFB01, + "fi", + (char) 0xFB02, + "fl", + (char) 0xFB03, + "ffi", + (char) 0xFB04, + "ffl", + (char) 0xFB05, + "ft", + (char) 0xFB06, + "st" }; + for (int i = 0; i < o.length; i += 2) + normalizeMap.put((Character) o[i], (String) o[i + 1]); + } + + /** Normalizes a character to a String of characters in the range 0x20-0x7F. + * Returns a String, because some characters are + * normalized to multiple characters (e.g. umlauts) and + * some characters are normalized to zero characters (e.g. special Unicode space chars). + * Returns null for the EndOfFile character -1 */ + public static String normalize(int c) { + // EOF + if (c == -1) return (null); + + // ASCII chars + if (c >= ' ' && c <= 128) return ("" + (char) c); + + // Upper case + boolean u = Character.isUpperCase(c); + char cu = (char) Character.toUpperCase(c); + + // Check map + if (normalizeMap.get(cu) != null) return (u ? normalizeMap.get(cu) : normalizeMap.get(cu).toLowerCase()); + + // ASCII + if (c < ' ') return (""); + + // Latin-1 + if (cu >= 0xC0 && cu <= 0xC5) return (u ? "A" : "a"); + if (cu >= 0xC8 && cu <= 0xCB) return (u ? "E" : "e"); + if (cu >= 0xCC && cu <= 0xCF) return (u ? "I" : "i"); + if (cu >= 0xD2 && cu <= 0xD8) return (u ? "O" : "o"); + if (cu >= 0x80 && cu <= 0xA0) return (" "); + + // Latin Extended-A + if (cu >= 0x100 && cu <= 0x105) return (u ? "A" : "a"); + if (cu >= 0x106 && cu <= 0x10D) return (u ? "C" : "c"); + if (cu >= 0x10E && cu <= 0x111) return (u ? "D" : "d"); + if (cu >= 0x112 && cu <= 0x11B) return (u ? "E" : "e"); + if (cu >= 0x11C && cu <= 0x123) return (u ? "G" : "g"); + if (cu >= 0x124 && cu <= 0x127) return (u ? "H" : "h"); + if (cu >= 0x128 && cu <= 0x131) return (u ? "I" : "i"); + if (cu >= 0x136 && cu <= 0x138) return (u ? "K" : "k"); + if (cu >= 0x139 && cu <= 0x142) return (u ? "L" : "l"); + if (cu >= 0x143 && cu <= 0x14B) return (u ? "N" : "n"); + if (cu >= 0x14C && cu <= 0x14F) return (u ? "O" : "o"); + if (cu >= 0x150 && cu <= 0x153) return (u ? "Oe" : "oe"); + if (cu >= 0x156 && cu <= 0x159) return (u ? "R" : "r"); + if (cu >= 0x15A && cu <= 0x161) return (u ? "S" : "s"); + if (cu >= 0x161 && cu <= 0x167) return (u ? "T" : "t"); + if (cu >= 0x176 && cu <= 0x178) return (u ? "Y" : "y"); + if (cu >= 0x179 && cu <= 0x17E) return (u ? "Z" : "z"); + + // General Punctuation + if (cu >= 0x2000 && cu <= 0x200A) return (" "); + if (cu >= 0x200B && cu <= 0x200F) return (""); + if (cu >= 0x2010 && cu <= 0x2015) return ("--"); + if (cu >= 0x2018 && cu <= 0x201B) return ("'"); + if (cu >= 0x201C && cu <= 0x201F) return ("\""); + if (cu >= 0x2029 && cu <= 0x202F) return (" "); + if (cu >= 0x203E && cu <= 0x2040) return ("-"); + if (cu >= 0x2056 && cu <= 0x205E) return ("."); + + return (defaultNormalizer.apply((char) c)); + } + + /** Eats a String of the form "%xx" from a string, where + * xx is a hexadecimal code. If xx is a UTF8 code start, + * tries to complete the UTF8-code and decodes it.*/ + public static char eatPercentage(String a, int[] n) { + // Length 0 + if (!a.startsWith("%") || a.length() < 3) { + n[0] = 0; + return ((char) 0); + } + char c; + // Try to parse first char + try { + c = (char) Integer.parseInt(a.substring(1, 3), 16); + } catch (Exception e) { + n[0] = -1; + return ((char) 0); + } + // For non-UTF8, return the char + int len = Utf8Length(c); + n[0] = 3; + if (len <= 1) return (c); + // Else collect the UTF8 + String dec = "" + c; + for (int i = 1; i < len; i++) { + try { + dec += (char) Integer.parseInt(a.substring(1 + i * 3, 3 + i * 3), 16); + } catch (Exception e) { + return (c); + } + } + // Try to decode the UTF8 + int[] eatLength = new int[1]; + char utf8 = eatUtf8(dec, eatLength); + if (eatLength[0] != len) return (c); + n[0] = len * 3; + return (utf8); + } + + /** Eats an HTML ampersand code from a String*/ + public static char eatAmpersand(String a, int[] n) { + n[0] = 0; + if (!a.startsWith("&")) return ((char) 0); + // Seek to ';' + // We also accept spaces and the end of the String as a delimiter + while (n[0] < a.length() && !Character.isSpaceChar(a.charAt(n[0])) && a.charAt(n[0]) != ';') + n[0]++; + if (n[0] <= 1) { + n[0] = -1; + return ((char) 0); + } + if (n[0] < a.length() && a.charAt(n[0]) == ';') { + a = a.substring(1, n[0]); + n[0]++; + } else { + a = a.substring(1, n[0]); + } + // Hexadecimal characters + if (a.startsWith("#x")) { + try { + return ((char) Integer.parseInt(a.substring(2), 16)); + } catch (Exception e) { + n[0] = -1; + return ((char) 0); + } + } + // Decimal characters + if (a.startsWith("#")) { + try { + return ((char) Integer.parseInt(a.substring(1))); + } catch (Exception e) { + n[0] = -1; + return ((char) 0); + } + } + // Others + if (ampersandMap.get(a) != null) return (ampersandMap.get(a)); + else if (ampersandMap.get(a.toLowerCase()) != null) return (ampersandMap.get(a.toLowerCase())); + n[0] = -1; + return ((char) 0); + } + + /** Tells from the first UTF-8 code character how long the code is. + * Returns -1 if the character is not an UTF-8 code start. + * Returns 1 if the character is ASCII<128*/ + public static int Utf8Length(char c) { + // 0xxx xxxx + if ((c & 0x80) == 0x00) return (1); + // 110x xxxx + if ((c & 0xE0) == 0xC0) return (2); + // 1110 xxxx + if ((c & 0xF0) == 0xE0) return (3); + // 1111 0xxx + if ((c & 0xF8) == 0xF0) return (4); + return (-1); + } + + /** Eats a UTF8 code from a String. There is also a built-in way in Java that converts + * UTF8 to characters and back, but it does not work with all characters. */ + public static char eatUtf8(String a, int[] n) { + if (a.length() == 0) { + n[0] = 0; + return ((char) 0); + } + n[0] = Utf8Length(a.charAt(0)); + if (a.length() >= n[0]) { + switch (n[0]) { + case 1: + return (a.charAt(0)); + case 2: + if ((a.charAt(1) & 0xC0) != 0x80) break; + return ((char) (((a.charAt(0) & 0x1F) << 6) + (a.charAt(1) & 0x3F))); + case 3: + if ((a.charAt(1) & 0xC0) != 0x80 || (a.charAt(2) & 0xC0) != 0x80) break; + return ((char) (((a.charAt(0) & 0x0F) << 12) + ((a.charAt(1) & 0x3F) << 6) + ((a.charAt(2) & 0x3F)))); + case 4: + if ((a.charAt(1) & 0xC0) != 0x80 || (a.charAt(2) & 0xC0) != 0x80 || (a.charAt(3) & 0xC0) != 0x80) break; + return ((char) (((a.charAt(0) & 0x07) << 18) + ((a.charAt(1) & 0x3F) << 12) + ((a.charAt(2) & 0x3F) << 6) + ((a.charAt(3) & 0x3F)))); + } + } + n[0] = -1; + return ((char) 0); + } + + /** Decodes all UTF8 characters in the string*/ + public static String decodeUTF8(String s) { + StringBuilder result = new StringBuilder(); + int[] eatLength = new int[1]; + while (s.length() != 0) { + char c = eatUtf8(s, eatLength); + if (eatLength[0] != -1) { + result.append(c); + s = s.substring(eatLength[0]); + } else { + result.append(s.charAt(0)); + s = s.substring(1); + } + } + return (result.toString()); + } + + /** Decodes all percentage characters in the string*/ + public static String decodePercentage(String s) { + StringBuilder result = new StringBuilder(); + int[] eatLength = new int[1]; + while (s.length() != 0) { + char c = eatPercentage(s, eatLength); + if (eatLength[0] > 1) { + result.append(c); + s = s.substring(eatLength[0]); + } else { + result.append(s.charAt(0)); + s = s.substring(1); + } + } + return (result.toString()); + } + + /** Fabian: This method cannot decode numeric hexadecimal ampersand codes. What is its purpose? TODO*/ + public static String decodeAmpersand_UNKNOWN(String s) { + if (s == null) { + return null; + } + StringBuffer sb = new StringBuffer(s.length()); + while (s != null && s.length() != 0) { + int i = s.indexOf("&"); + if (i == -1) { + sb.append(s); + s = null; + } else { + boolean space = false; + boolean end = false; + sb.append(s.substring(0, i)); + s = s.substring(i); + int j1 = s.indexOf(";"); + int j2 = s.indexOf(" "); + int j = -1; + if (j1 == -1 || j2 == -1) { + if (j1 == -1 && j2 == -1) { + end = true; + j = s.length(); + } else if (j1 == -1) { + j = j2; + } else if (j2 == -1) { + j = j1; + } + } else if (j1 < j2) { + j = j1; + } else if (j1 > j2) { + j = j2; + space = true; + } + String a = s.substring(1, j); + if (ampersandMap.get(a) != null) { + sb.append(ampersandMap.get(a)); + if (space) { + sb.append(' '); + } + } else if (a.startsWith("#")) { + try { + sb.append(((char) Integer.parseInt(a.substring(1)))); + } catch (Exception e) { + sb.append(a); + } + if (space) { + sb.append(' '); + } + } else { + if (end) { + sb.append(s.substring(0, j)); + } else { + sb.append(s.substring(0, j + 1)); + } + } + if (end) { + s = s.substring(j); + } else { + s = s.substring(j + 1); + } + } + } + return sb.toString(); + } + + public static String decodeAmpersand(String s, PositionTracker posTracker) { + if (s == null) { + return null; + } + int pos = 0; + int difference; + StringBuffer sb = new StringBuffer(s.length()); + while (s != null && s.length() != 0) { + int i = s.indexOf("&"); + if (i == -1) { + sb.append(s); + s = null; + } else { + boolean space = false; + boolean end = false; + sb.append(s.substring(0, i)); + s = s.substring(i); + pos += i; + int j1 = s.indexOf(";"); + int j2 = s.indexOf(" "); + int j = -1; + if (j1 == -1 || j2 == -1) { + if (j1 == -1 && j2 == -1) { + end = true; + j = s.length(); + } else if (j1 == -1) { + j = j2; + } else if (j2 == -1) { + j = j1; + } + } else if (j1 < j2) { + j = j1; + } else if (j1 > j2) { + j = j2; + space = true; + } + pos += (j + 1); + String a = s.substring(1, j); + if (ampersandMap.get(a) != null) { + sb.append(ampersandMap.get(a)); + difference = 1 - (j + 1); + if (space) { + sb.append(' '); + difference++; + } + posTracker.addPositionChange(pos, difference); + } else { + if (end) { + sb.append(s.substring(0, j)); + } else { + sb.append(s.substring(0, j + 1)); + } + } + if (end) { + s = s.substring(j); + } else { + s = s.substring(j + 1); + } + } + } + posTracker.closeRun(); + return sb.toString(); + } + + /** Decodes all ampersand sequences in the string*/ + public static String decodeAmpersand(String s) { + if(s==null || s.indexOf('&')==-1) return(s); + StringBuilder result = new StringBuilder(); + int[] eatLength = new int[1];// add this in order to multithread safe + while (s.length() != 0) { + char c = eatAmpersand(s, eatLength); + if (eatLength[0] > 1) { + result.append(c); + s = s.substring(eatLength[0]); + } else { + result.append(s.charAt(0)); + s = s.substring(1); + } + } + return (result.toString()); + } + + /** Decodes all backslash characters in the string */ + public static String decodeBackslash(String s) { + if(s==null || s.indexOf('\\')==-1) return(s); + StringBuilder result = new StringBuilder(); + int[] eatLength = new int[1]; + while (s.length() != 0) { + char c = eatBackslash(s, eatLength); + if (eatLength[0] > 1) { + result.append(c); + s = s.substring(eatLength[0]); + } else { + result.append(s.charAt(0)); + s = s.substring(1); + } + } + return (result.toString()); + } + + /** Used for encoding selected characters*/ + public static interface Legal { + public boolean isLegal(char c); + } + + /** Encodes with backslash all illegal characters*/ + public static String encodeBackslash(CharSequence s, Legal legal) { + StringBuilder b=new StringBuilder((int)(s.length()*1.5)); + for(int i=0;i<s.length();i++) { + if(legal.isLegal(s.charAt(i))) { + b.append(s.charAt(i)); + } else { + if(charToBackslash.containsKey(s.charAt(i))) { + b.append(charToBackslash.get(s.charAt(i))); + continue; + } + b.append("\\u"); + String hex = Integer.toHexString(s.charAt(i)); + for(int j=0;j<4-hex.length();j++) + b.append('0'); + b.append(hex); + } + } + return(b.toString()); + } + + /** Eats a backslash sequence from a String */ + public static char eatBackslash(String a, int[] n) { + if (!a.startsWith("\\")) { + n[0] = 0; + return ((char) 0); + } + // Unicodes BS u XXXX + if (a.startsWith("\\u")) { + try { + n[0] = 6; + return ((char) Integer.parseInt(a.substring(2, 6), 16)); + } catch (Exception e) { + n[0] = -1; + return ((char) 0); + } + } + // Unicodes BS uu XXXX + if (a.startsWith("\\uu")) { + try { + n[0] = 7; + return ((char) Integer.parseInt(a.substring(3, 7), 16)); + } catch (Exception e) { + n[0] = -1; + return ((char) 0); + } + } + // Classical escape sequences + if (a.startsWith("\\b")) { + n[0] = 2; + return ((char) 8); + } + if (a.startsWith("\\t")) { + n[0] = 2; + return ((char) 9); + } + if (a.startsWith("\\n")) { + n[0] = 2; + return ((char) 10); + } + if (a.startsWith("\\f")) { + n[0] = 2; + return ((char) 12); + } + if (a.startsWith("\\r")) { + n[0] = 2; + return ((char) 13); + } + if (a.startsWith("\\\\")) { + n[0] = 2; + return ('\\'); + } + if (a.startsWith("\\\"")) { + n[0] = 2; + return ('"'); + } + if (a.startsWith("\\'")) { + n[0] = 2; + return ('\''); + } + // Octal codes + n[0] = 1; + while (n[0] < a.length() && a.charAt(n[0]) >= '0' && a.charAt(n[0]) <= '8') + n[0]++; + if (n[0] == 1) { + n[0] = 0; + return ((char) 0); + } + try { + return ((char) Integer.parseInt(a.substring(1, n[0]), 8)); + } catch (Exception e) { + } + n[0] = -1; + return ((char) 0); + } + + /** Replaces all codes in a String by the 16 bit Unicode characters */ + public static String decode(String s) { + StringBuilder b = new StringBuilder(); + int[] eatLength = new int[1]; + while (s.length() > 0) { + char c = eatPercentage(s, eatLength); + if (eatLength[0] <= 0) { + c = eatAmpersand(s, eatLength); + if (eatLength[0] <= 0) { + c = eatBackslash(s, eatLength); + if (eatLength[0] <= 0) { + c = eatUtf8(s, eatLength); + if (eatLength[0] <= 0) { + c = s.charAt(0); + eatLength[0] = 1; + } + } + } + } + b.append(c); + s = s.substring(eatLength[0]); + } + return (b.toString()); + } + + /** Encodes a character to UTF8 (if necessary)*/ + public static String encodeUTF8(int c) { + if (c <= 0x7F) return ("" + (char) c); + if (c <= 0x7FF) return ("" + (char) (0xC0 + ((c >> 6) & 0x1F)) + (char) (0x80 + (c & 0x3F))); + if (c <= 0xFFFF) return ("" + (char) (0xE0 + ((c >> 12) & 0x0F)) + (char) (0x80 + ((c >> 6) & 0x3F)) + (char) (0x80 + (c & 0x3F))); + return ("" + c); + } + + /** Encodes a character to a backslash code (if necessary)*/ + public static String encodeBackslash(char c) { + if (isAlphanumeric(c) || c == ' ') return ("" + c); + String hex = Integer.toHexString(c); + while (hex.length() < 4) + hex = "0" + hex; + return ("\\u" + hex); + } + + /** Encodes a character to a backslash code (if not alphanumeric)*/ + public static String encodeBackslashToAlphanumeric(char c) { + if (isAlphanumeric(c) || c == '_') return ("" + c); + String hex = Integer.toHexString(c); + while (hex.length() < 4) + hex = "0" + hex; + return ("\\u" + hex); + } + + /** Encodes a character to a backslash code (if not ASCII)*/ + public static String encodeBackslashToASCII(char c) { + if (c >= 32 && c < 128 && c != '\\' && c != '"') return ("" + c); + String hex = Integer.toHexString(c); + while (hex.length() < 4) + hex = "0" + hex; + return ("\\u" + hex); + } + + /** Encodes a character to an HTML-Ampersand code (if necessary)*/ + public static String encodeAmpersand(char c) { + String s; + if (null != (s = charToAmpersand.get(c))) return (s); + if (c < 128 && c >= 32) return ("" + c); + else return ("&#" + ((int) c) + ";"); + } + + /** Encodes a character to an HTML-Ampersand code (if necessary)*/ + public static String encodeAmpersandToAlphanumeric(char c) { + if (isAlphanumeric(c) || c == '_') return ("" + c); + return ("&#" + ((int) c) + ";"); + } + + /** Encodes a character to an Percentage code (if necessary). + * If the character is greater than 0x80, the character is converted to + * a UTF8-sequence and this sequence is encoded as percentage codes. */ + public static String encodePercentage(char c) { + if (isAlphanumeric(c)) return ("" + c); + if (c < 16) return ("%0" + Integer.toHexString(c).toUpperCase()); + if (c < 128) return ("%" + Integer.toHexString(c).toUpperCase()); + String s = encodeUTF8(c); + String result = ""; + for (int i = 0; i < s.length(); i++) { + result += "%" + Integer.toHexString(s.charAt(i)).toUpperCase(); + } + return (result); + } + + /** + * Encodes a String with reserved XML characters into a valid xml string for attributes. + * @param str + * @return + */ + public static String encodeXmlAttribute(String str) { + if (str == null) return null; + int len = str.length(); + if (len == 0) return str; + StringBuffer encoded = new StringBuffer(); + for (int i = 0; i < len; i++) { + char c = str.charAt(i); + if (c == '<') encoded.append("<"); + else if (c == '\"') encoded.append("""); + else if (c == '>') encoded.append(">"); + else if (c == '\'') encoded.append("'"); + else if (c == '&') encoded.append("&"); + else encoded.append(c); + } + return encoded.toString(); + } + + /** Tells whether a char is in a range*/ + public static boolean in(char c, char a, char b) { + return (c >= a && c <= b); + } + + /** Tells whether a char is in a string*/ + public static boolean in(char c, String s) { + return (s.indexOf(c) != -1); + } + + /** Tells whether a char is alphanumeric in the sense of URIs*/ + public static boolean isAlphanumeric(char c) { + return (in(c, 'a', 'z') || in(c, 'A', 'Z') || in(c, '0', '9')); + } + + /** Tells whether a char is reserved in the sense of URIs*/ + public static boolean isReserved(char c) { + return (isSubDelim(c) || isGenDelim(c)); + } + + /** Tells whether a char is unreserved in the sense of URIs (not the same as !reserved)*/ + public static boolean isUnreserved(char c) { + return (isAlphanumeric(c) || in(c, "-._~")); + } + + /** Tells whether a string is escaped in the sense of URIs*/ + public static boolean isEscaped(String s) { + return (s.matches("%[0-9A-Fa-f]{2}")); + } + + /** Tells whether a char is a sub-delimiter in the sense of URIs*/ + public static boolean isSubDelim(char c) { + return (in(c, "!$&'()*+,=")); + } + + /** Tells whether a char is a general delimiter in the sense of URIs*/ + public static boolean isGenDelim(char c) { + return (in(c, ":/?#[]@")); + } + + /** Tells whether a char is a valid path component in the sense of URIs*/ + public static boolean isPchar(char c) { + return (isUnreserved(c) || isSubDelim(c) || in(c, "@")); + } + + /** Encodes a char to percentage code, if it is not a path character in the sense of URIs*/ + public static String encodeURIPathComponent(char c) { + if (isPchar(c)) return ("" + c); + else return (Char.encodePercentage(c)); + } + + /** Encodes a char to percentage code, if it is not a path character in the sense of URIs*/ + public static String encodeURIPathComponent(String s) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + result.append(Char.encodeURIPathComponent(s.charAt(i))); + } + return (result.toString()); + } + + /** Encodes a char to percentage code, if it is not a path character in the sense of XMLs*/ + public static String encodeURIPathComponentXML(String s) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '&') result.append(Char.encodePercentage(s.charAt(i))); + else if (s.charAt(i) == '"') result.append(Char.encodePercentage(s.charAt(i))); + else result.append(Char.encodeURIPathComponent(s.charAt(i))); + } + return (result.toString()); + } + + /** Decodes a URI path component*/ + public static String decodeURIPathComponent(String s) { + return (Char.decodePercentage(s)); + } + + /** Encodes a String to UTF8 */ + public static String encodeUTF8(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeUTF8(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by Backslash codes */ + public static String encodeBackslash(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeBackslash(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by Backslash codes (if not alphanumeric)*/ + public static String encodeBackslashToAlphanumeric(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeBackslashToAlphanumeric(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by Backslash codes (if not ASCII)*/ + public static String encodeBackslashToASCII(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeBackslashToASCII(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by HTML Ampersand codes */ + public static String encodeAmpersand(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeAmpersand(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by HTML Ampersand codes */ + public static String encodeAmpersandToAlphanumeric(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodeAmpersandToAlphanumeric(c.charAt(i))); + } + return (r.toString()); + } + + /** Replaces non-normal characters in a String by Percentage codes. + * If a character is greater than 0x80, the character is converted to + * a UTF8-sequence and this sequence is encoded as percentage codes. */ + public static String encodePercentage(String c) { + StringBuilder r = new StringBuilder(); + for (int i = 0; i < c.length(); i++) { + r.append(encodePercentage(c.charAt(i))); + } + return (r.toString()); + } + + /** Decodes all codes in a String and normalizes all chars */ + public static String decodeAndNormalize(String s) { + return (normalize(decode(s))); + } + + /** Normalizes all chars in a String to characters 0x20-0x7F */ + public static String normalize(String s) { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < s.length(); i++) + b.append(normalize(s.charAt(i))); + return (b.toString()); + } + + /** Returns the last character of a String or 0*/ + public static char last(CharSequence s) { + return (s.length() == 0 ? (char) 0 : s.charAt(s.length() - 1)); + } + + /** Returns the String without the last character */ + public static String cutLast(String s) { + return (s.length() == 0 ? "" : s.substring(0, s.length() - 1)); + } + + /** Cuts the last character */ + public static StringBuilder cutLast(StringBuilder s) { + s.setLength(s.length() - 1); + return (s); + } + + /** Returns an HTML-String of the String */ + public static String toHTML(String s) { + return (Char.encodeAmpersand(s).replace(" ", "<BR>")); + } + + /** Returns the chars of a String in hex */ + public static String hexAll(String s) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + result.append(Integer.toHexString(s.charAt(i)).toUpperCase()).append(' '); + } + return (result.toString()); + } + + /** Replaces special characters in the string by hex codes (cannot be undone)*/ + public static String encodeHex(String s) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (isAlphanumeric(c)) result.append(c); + else result.append(Integer.toHexString(s.charAt(i)).toUpperCase()); + } + return (result.toString()); + } + + /** Upcases the first character in a String*/ + public static String upCaseFirst(String s) { + if (s == null || s.length() == 0) return (s); + return (Character.toUpperCase(s.charAt(0)) + s.substring(1)); + } + + /** Lowcases the first character in a String*/ + public static String lowCaseFirst(String s) { + if (s == null || s.length() == 0) return (s); + return (Character.toLowerCase(s.charAt(0)) + s.substring(1)); + } + + /** Returns a string of the given length, fills with spaces if necessary */ + public static CharSequence truncate(CharSequence s, int len) { + if (s.length() == len) return (s); + if (s.length() > len) return (s.subSequence(0, len)); + StringBuilder result = new StringBuilder(s); + while (result.length() < len) + result.append(' '); + return (result); + } + + /** Capitalizes words and lowercases the rest*/ + public static String capitalize(String s) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (i == 0 || i > 0 && !Character.isLetterOrDigit(s.charAt(i - 1))) c = Character.toUpperCase(c); + else c = Character.toLowerCase(c); + result.append(c); + } + return (result.toString()); + } + + /** TRUE if the Charsequence ends with the string */ + public static boolean endsWith(CharSequence s, String end) { + return (s.length() >= end.length() && s.subSequence(s.length() - end.length(), s.length()).equals(end)); + } + + /** Test routine */ + public static void main(String argv[]) throws Exception { + System.out.println("Enter a string with HTML ampersand codes, umlauts and/or UTF-8 codes and hit ENTER."); + System.out.println("Press CTRL+C to abort"); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + while (true) { + String s = in.readLine(); + System.out.println("Decoded: " + (s = decode(s))); + System.out.println("Normalized: " + normalize(s)); + System.out.println("As UTF8: " + encodeUTF8(s)); + System.out.println("As percentage: " + encodePercentage(s)); + System.out.println("As backslash: " + encodeBackslash(s)); + System.out.println("As ampersand: " + encodeAmpersand(s)); + System.out.println("As URI component: " + encodeURIPathComponent(s)); + } + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PlingStemmer.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PlingStemmer.java new file mode 100644 index 0000000..d4dc2fb --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PlingStemmer.java
@@ -0,0 +1,925 @@ +package org.grails.datastore.gorm.neo4j.parsers; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.Set; + +import org.grails.datastore.gorm.neo4j.datatypes.FinalMap; +import org.grails.datastore.gorm.neo4j.datatypes.FinalSet; + +/** +This class is part of the Java Tools (see http://mpii.de/yago-naga/javatools). +It is licensed under the Creative Commons Attribution License +(see http://creativecommons.org/licenses/by/3.0) by +the YAGO-NAGA team (see http://mpii.de/yago-naga). + + + + + + The PlingStemmer stems an English noun (plural or singular) to its singular + form. It deals with "firemen"->"fireman", it knows Greek stuff like + "appendices"->"appendix" and yes, it was a lot of work to compile these exceptions. + Examples: + <PRE> + System.out.println(PlingStemmer.stem("boy")); + ----> boy + System.out.println(PlingStemmer.stem("boys")); + ----> boy + System.out.println(PlingStemmer.stem("biophysics")); + ----> biophysics + System.out.println(PlingStemmer.stem("automata")); + ----> automaton + System.out.println(PlingStemmer.stem("genus")); + ----> genus + System.out.println(PlingStemmer.stem("emus")); + ----> emu + </PRE><P> + + There are a number of word forms that can either be plural or singular. + Examples include "physics" (the science or the plural of "physic" (the + medicine)), "quarters" (the housing or the plural of "quarter" (1/4)) + or "people" (the singular of "peoples" or the plural of "person"). In + these cases, the stemmer assumes the word is a plural form and returns + the singular form. The methods isPlural, isSingular and isPluralAndSingular + can be used to differentiate the cases.<P> + + It cannot be guaranteed that the stemmer correctly stems a plural word + or correctly ignores a singular word -- let alone that it treats an + ambiguous word form in the way expected by the user.<P> + + The PlingStemmer uses material from <A HREF=http://wordnet.princeton.edu/>WordNet</A>.<P> + It requires the class FinalSet from the <A HREF=http://www.mpii.mpg.de/~suchanek/downloads/javatools> + Java Tools</A>. +*/ +public class PlingStemmer { + + /** Tells whether a word form is plural. This method just checks whether the + * stem method alters the word */ + public static boolean isPlural(String s) { + return(!s.equals(stem(s))); + } + + /** Tells whether a word form is singular. Note that a word can be both plural and singular */ + public static boolean isSingular(String s) { + return(singAndPlur.contains(s.toLowerCase()) || !isPlural(s)); + } + + /** Tells whether a word form is the singular form of one word and at + * the same time the plural form of another.*/ + public static boolean isSingularAndPlural(String s) { + return(singAndPlur.contains(s.toLowerCase())); + } + + /** Cuts a suffix from a string (that is the number of chars given by the suffix) */ + public static String cut(String s, String suffix) { + return(s.substring(0,s.length()-suffix.length())); + } + + /** Returns true if a word is probably not Latin */ + public static boolean noLatin(String s) { + return(s.indexOf('h')>0 || s.indexOf('j')>0 || s.indexOf('k')>0 || + s.indexOf('w')>0 || s.indexOf('y')>0 || s.indexOf('z')>0 || + s.indexOf("ou")>0 || s.indexOf("sh")>0 || s.indexOf("ch")>0 || + s.endsWith("aus")); + } + + /** Returns true if a word is probably Greek */ + private static boolean greek(String s) { + return(s.indexOf("ph")>0 || s.indexOf('y')>0 && s.endsWith("nges")); + } + + /** Stems an English noun */ + public static String stem(String s) { + String stem = s; + + // Handle irregular ones + String irreg=irregular.get(s); + if(irreg!=null) return(stem=irreg); + + // -on to -a + if(categoryON_A.contains(s)) return(stem=cut(s,"a")+"on"); + + // -um to -a + if(categoryUM_A.contains(s)) return(stem=cut(s,"a")+"um"); + + // -x to -ices + if(categoryIX_ICES.contains(s)) return(stem=cut(s,"ices")+"ix"); + + // -o to -i + if(categoryO_I.contains(s)) return(stem=cut(s,"i")+"o"); + + // -se to ses + if(categorySE_SES.contains(s)) return(stem=cut(s,"s")); + + // -is to -es + if(categoryIS_ES.contains(s) || s.endsWith("theses")) return(stem=cut(s,"es")+"is"); + + // -us to -i + if(categoryUS_I.contains(s)) return(stem=cut(s,"i")+"us"); + //Wrong plural + if(s.endsWith("uses") && (categoryUS_I.contains(cut(s,"uses")+"i") || + s.equals("genuses") || s.equals("corpuses"))) return(stem=cut(s,"es")); + + // -ex to -ices + if(categoryEX_ICES.contains(s)) return(stem=cut(s,"ices")+"ex"); + + // Words that do not inflect in the plural + if(s.endsWith("ois") || s.endsWith("itis") || category00.contains(s) || categoryICS.contains(s)) return(stem=s); + + // -en to -ina + // No other common words end in -ina + if(s.endsWith("ina")) return(stem=cut(s,"en")); + + // -a to -ae + // No other common words end in -ae + if(s.endsWith("ae")) return(stem=cut(s,"e")); + + // -a to -ata + // No other common words end in -ata + if(s.endsWith("ata")) return(stem=cut(s,"ta")); + + // trix to -trices + // No common word ends with -trice(s) + if(s.endsWith("trices")) return(stem=cut(s,"trices")+"trix"); + + // -us to -us + //No other common word ends in -us, except for false plurals of French words + //Catch words that are not latin or known to end in -u + if(s.endsWith("us") && !s.endsWith("eaus") && !s.endsWith("ieus") && !noLatin(s) + && !categoryU_US.contains(s)) return(stem=s); + + // -tooth to -teeth + // -goose to -geese + // -foot to -feet + // -zoon to -zoa + //No other common words end with the indicated suffixes + if(s.endsWith("teeth")) return(stem=cut(s,"teeth")+"tooth"); + if(s.endsWith("geese")) return(stem=cut(s,"geese")+"goose"); + if(s.endsWith("feet")) return(stem=cut(s,"feet")+"foot"); + if(s.endsWith("zoa")) return(stem=cut(s,"zoa")+"zoon"); + + // -eau to -eaux + //No other common words end in eaux + if(s.endsWith("eaux")) return(stem=cut(s,"x")); + + // -ieu to -ieux + //No other common words end in ieux + if(s.endsWith("ieux")) return(stem=cut(s,"x")); + + // -nx to -nges + // Pay attention not to kill words ending in -nge with plural -nges + // Take only Greek words (works fine, only a handfull of exceptions) + if(s.endsWith("nges") && greek(s)) return(stem=cut(s,"nges")+"nx"); + + // -[sc]h to -[sc]hes + //No other common word ends with "shes", "ches" or "she(s)" + //Quite a lot end with "che(s)", filter them out + if(s.endsWith("shes") || s.endsWith("ches") && !categoryCHE_CHES.contains(s)) return(stem=cut(s,"es")); + + // -ss to -sses + // No other common singular word ends with "sses" + // Filter out those ending in "sse(s)" + if(s.endsWith("sses") && !categorySSE_SSES.contains(s) && !s.endsWith("mousses")) return(stem=cut(s,"es")); + + // -x to -xes + // No other common word ends with "xe(s)" except for "axe" + if(s.endsWith("xes") && !s.equals("axes")) return(stem=cut(s,"es")); + + // -[nlw]ife to -[nlw]ives + //No other common word ends with "[nlw]ive(s)" except for olive + if(s.endsWith("nives") || s.endsWith("lives") && !s.endsWith("olives") || + s.endsWith("wives")) return(stem=cut(s,"ves")+"fe"); + + // -[aeo]lf to -ves exceptions: valve, solve + // -[^d]eaf to -ves exceptions: heave, weave + // -arf to -ves no exception + if(s.endsWith("alves") && !s.endsWith("valves") || + s.endsWith("olves") && !s.endsWith("solves") || + s.endsWith("eaves") && !s.endsWith("heaves") && !s.endsWith("weaves") || + s.endsWith("arves") ) return(stem=cut(s,"ves")+"f"); + + // -y to -ies + // -ies is very uncommon as a singular suffix + // but -ie is quite common, filter them out + if(s.endsWith("ies") && !categoryIE_IES.contains(s)) return(stem=cut(s,"ies")+"y"); + + // -o to -oes + // Some words end with -oe, so don't kill the "e" + if(s.endsWith("oes") && !categoryOE_OES.contains(s)) return(stem=cut(s,"es")); + + // -s to -ses + // -z to -zes + // no words end with "-ses" or "-zes" in singular + if(s.endsWith("ses") || s.endsWith("zes") ) return(stem=cut(s,"es")); + + // - to -s + if(s.endsWith("s") && !s.endsWith("ss") && !s.endsWith("is")) return(stem=cut(s,"s")); + + return stem; + } + + /** Words that end in "-se" in their plural forms (like "nurse" etc.)*/ + public static Set<String> categorySE_SES=new FinalSet<String>( + "nurses", + "cruises", + "premises", + "houses", + "courses", + "cases" + ); + + /** Words that do not have a distinct plural form (like "atlas" etc.)*/ + public static Set<String> category00=new FinalSet<String>( + "alias", + "asbestos", + "atlas", + "barracks", + "bathos", + "bias", + "breeches", + "britches", + "canvas", + "chaos", + "clippers", + "contretemps", + "corps", + "cosmos", + "crossroads", + "diabetes", + "ethos", + "gallows", + "gas", + "graffiti", + "headquarters", + "herpes", + "high-jinks", + "innings", + "jackanapes", + "lens", + "means", + "measles", + "mews", + "mumps", + "news", + "pathos", + "pincers", + "pliers", + "proceedings", + "rabies", + "rhinoceros", + "sassafras", + "scissors", + "series", + "shears", + "species", + "tuna" + ); + + /** Words that change from "-um" to "-a" (like "curriculum" etc.), listed in their plural forms*/ + public static Set<String> categoryUM_A=new FinalSet<String>( + "addenda", + "agenda", + "aquaria", + "bacteria", + "candelabra", + "compendia", + "consortia", + "crania", + "curricula", + "data", + "desiderata", + "dicta", + "emporia", + "enconia", + "errata", + "extrema", + "gymnasia", + "honoraria", + "interregna", + "lustra", + "maxima", + "media", + "memoranda", + "millenia", + "minima", + "momenta", + "optima", + "ova", + "phyla", + "quanta", + "rostra", + "spectra", + "specula", + "stadia", + "strata", + "symposia", + "trapezia", + "ultimata", + "vacua", + "vela" + ); + + /** Words that change from "-on" to "-a" (like "phenomenon" etc.), listed in their plural forms*/ + public static Set<String> categoryON_A=new FinalSet<String>( + "aphelia", + "asyndeta", + "automata", + "criteria", + "hyperbata", + "noumena", + "organa", + "perihelia", + "phenomena", + "prolegomena" + ); + + /** Words that change from "-o" to "-i" (like "libretto" etc.), listed in their plural forms*/ + public static Set<String> categoryO_I=new FinalSet<String>( + "alti", + "bassi", + "canti", + "contralti", + "crescendi", + "libretti", + "soli", + "soprani", + "tempi", + "virtuosi" + ); + + /** Words that change from "-us" to "-i" (like "fungus" etc.), listed in their plural forms*/ + public static Set<String> categoryUS_I=new FinalSet<String>( + "alumni", + "bacilli", + "cacti", + "foci", + "fungi", + "genii", + "hippopotami", + "incubi", + "nimbi", + "nuclei", + "nucleoli", + "octopi", + "radii", + "stimuli", + "styli", + "succubi", + "syllabi", + "termini", + "tori", + "umbilici", + "uteri" + ); + + /** Words that change from "-ix" to "-ices" (like "appendix" etc.), listed in their plural forms*/ + public static Set<String> categoryIX_ICES=new FinalSet<String>( + "appendices", + "cervices" + ); + + /** Words that change from "-is" to "-es" (like "axis" etc.), listed in their plural forms*/ + public static Set<String> categoryIS_ES=new FinalSet<String>( + // plus everybody ending in theses + "analyses", + "axes", + "bases", + "crises", + "diagnoses", + "ellipses", + "emphases", + "neuroses", + "oases", + "paralyses", + "synopses" + ); + + /** Words that change from "-oe" to "-oes" (like "toe" etc.), listed in their plural forms*/ + public static Set<String> categoryOE_OES=new FinalSet<String>( + "aloes", + "backhoes", + "beroes", + "canoes", + "chigoes", + "cohoes", + "does", + "felloes", + "floes", + "foes", + "gumshoes", + "hammertoes", + "hoes", + "hoopoes", + "horseshoes", + "leucothoes", + "mahoes", + "mistletoes", + "oboes", + "overshoes", + "pahoehoes", + "pekoes", + "roes", + "shoes", + "sloes", + "snowshoes", + "throes", + "tic-tac-toes", + "tick-tack-toes", + "ticktacktoes", + "tiptoes", + "tit-tat-toes", + "toes", + "toetoes", + "tuckahoes", + "woes" + ); + + /** Words that change from "-ex" to "-ices" (like "index" etc.), listed in their plural forms*/ + public static Set<String> categoryEX_ICES=new FinalSet<String>( + "apices", + "codices", + "cortices", + "indices", + "latices", + "murices", + "pontifices", + "silices", + "simplices", + "vertices", + "vortices" + ); + + /** Words that change from "-u" to "-us" (like "emu" etc.), listed in their plural forms*/ + public static Set<String> categoryU_US=new FinalSet<String>( + "apercus", + "barbus", + "cornus", + "ecrus", + "emus", + "fondus", + "gnus", + "iglus", + "mus", + "nandus", + "napus", + "poilus", + "quipus", + "snafus", + "tabus", + "tamandus", + "tatus", + "timucus", + "tiramisus", + "tofus", + "tutus" + ); + + /** Words that change from "-sse" to "-sses" (like "finesse" etc.), listed in their plural forms*/ + public static Set<String> categorySSE_SSES=new FinalSet<String>( + //plus those ending in mousse + "bouillabaisses", + "coulisses", + "crevasses", + "crosses", + "cuisses", + "demitasses", + "ecrevisses", + "fesses", + "finesses", + "fosses", + "impasses", + "lacrosses", + "largesses", + "masses", + "noblesses", + "palliasses", + "pelisses", + "politesses", + "posses", + "tasses", + "wrasses" + ); + + /** Words that change from "-che" to "-ches" (like "brioche" etc.), listed in their plural forms*/ + public static Set<String> categoryCHE_CHES=new FinalSet<String>( + "adrenarches", + "attaches", + "avalanches", + "barouches", + "brioches", + "caches", + "caleches", + "caroches", + "cartouches", + "cliches", + "cloches", + "creches", + "demarches", + "douches", + "gouaches", + "guilloches", + "headaches", + "heartaches", + "huaraches", + "menarches", + "microfiches", + "moustaches", + "mustaches", + "niches", + "panaches", + "panoches", + "pastiches", + "penuches", + "pinches", + "postiches", + "psyches", + "quiches", + "schottisches", + "seiches", + "soutaches", + "synecdoches", + "thelarches", + "troches" + ); + + /** Words that end with "-ics" and do not exist as nouns without the 's' (like "aerobics" etc.)*/ + public static Set<String> categoryICS=new FinalSet<String>( + "aerobatics", + "aerobics", + "aerodynamics", + "aeromechanics", + "aeronautics", + "alphanumerics", + "animatronics", + "apologetics", + "architectonics", + "astrodynamics", + "astronautics", + "astrophysics", + "athletics", + "atmospherics", + "autogenics", + "avionics", + "ballistics", + "bibliotics", + "bioethics", + "biometrics", + "bionics", + "bionomics", + "biophysics", + "biosystematics", + "cacogenics", + "calisthenics", + "callisthenics", + "catoptrics", + "civics", + "cladistics", + "cryogenics", + "cryonics", + "cryptanalytics", + "cybernetics", + "cytoarchitectonics", + "cytogenetics", + "diagnostics", + "dietetics", + "dramatics", + "dysgenics", + "econometrics", + "economics", + "electromagnetics", + "electronics", + "electrostatics", + "endodontics", + "enterics", + "ergonomics", + "eugenics", + "eurhythmics", + "eurythmics", + "exodontics", + "fibreoptics", + "futuristics", + "genetics", + "genomics", + "geographics", + "geophysics", + "geopolitics", + "geriatrics", + "glyptics", + "graphics", + "gymnastics", + "hermeneutics", + "histrionics", + "homiletics", + "hydraulics", + "hydrodynamics", + "hydrokinetics", + "hydroponics", + "hydrostatics", + "hygienics", + "informatics", + "kinematics", + "kinesthetics", + "kinetics", + "lexicostatistics", + "linguistics", + "lithoglyptics", + "liturgics", + "logistics", + "macrobiotics", + "macroeconomics", + "magnetics", + "magnetohydrodynamics", + "mathematics", + "metamathematics", + "metaphysics", + "microeconomics", + "microelectronics", + "mnemonics", + "morphophonemics", + "neuroethics", + "neurolinguistics", + "nucleonics", + "numismatics", + "obstetrics", + "onomastics", + "orthodontics", + "orthopaedics", + "orthopedics", + "orthoptics", + "paediatrics", + "patristics", + "patristics", + "pedagogics", + "pediatrics", + "periodontics", + "pharmaceutics", + "pharmacogenetics", + "pharmacokinetics", + "phonemics", + "phonetics", + "phonics", + "photomechanics", + "physiatrics", + "pneumatics", + "poetics", + "politics", + "pragmatics", + "prosthetics", + "prosthodontics", + "proteomics", + "proxemics", + "psycholinguistics", + "psychometrics", + "psychonomics", + "psychophysics", + "psychotherapeutics", + "robotics", + "semantics", + "semiotics", + "semitropics", + "sociolinguistics", + "stemmatics", + "strategics", + "subtropics", + "systematics", + "tectonics", + "telerobotics", + "therapeutics", + "thermionics", + "thermodynamics", + "thermostatics" + ); + + /** Words that change from "-ie" to "-ies" (like "auntie" etc.), listed in their plural forms*/ + public static Set<String> categoryIE_IES=new FinalSet<String>( + "aeries", + "anomies", + "aunties", + "baddies", + "beanies", + "birdies", + "boccies", + "bogies", + "bolshies", + "bombies", + "bonhomies", + "bonxies", + "booboisies", + "boogies", + "boogie-woogies", + "bookies", + "booties", + "bosies", + "bourgeoisies", + "brasseries", + "brassies", + "brownies", + "budgies", + "byrnies", + "caddies", + "calories", + "camaraderies", + "capercaillies", + "capercailzies", + "cassies", + "catties", + "causeries", + "charcuteries", + "chinoiseries", + "collies", + "commies", + "cookies", + "coolies", + "coonties", + "cooties", + "corries", + "coteries", + "cowpies", + "cowries", + "cozies", + "crappies", + "crossties", + "curies", + "dachsies", + "darkies", + "dassies", + "dearies", + "dickies", + "dies", + "dixies", + "doggies", + "dogies", + "dominies", + "dovekies", + "eyries", + "faeries", + "falsies", + "floozies", + "folies", + "foodies", + "freebies", + "gaucheries", + "gendarmeries", + "genies", + "ghillies", + "gillies", + "goalies", + "goonies", + "grannies", + "grotesqueries", + "groupies", + "hankies", + "hippies", + "hoagies", + "honkies", + "hymies", + "indies", + "junkies", + "kelpies", + "kilocalories", + "knobkerries", + "koppies", + "kylies", + "laddies", + "lassies", + "lies", + "lingeries", + "magpies", + "magpies", + "marqueteries", + "mashies", + "mealies", + "meanies", + "menageries", + "millicuries", + "mollies", + "facts1", + "moxies", + "neckties", + "newbies", + "nighties", + "nookies", + "oldies", + "organdies", + "panties", + "parqueteries", + "passementeries", + "patisseries", + "pies", + "pinkies", + "pixies", + "porkpies", + "potpies", + "prairies", + "preemies", + "premies", + "punkies", + "pyxies", + "quickies", + "ramies", + "reveries", + "rookies", + "rotisseries", + "scrapies", + "sharpies", + "smoothies", + "softies", + "stoolies", + "stymies", + "swaggies", + "sweeties", + "talkies", + "techies", + "ties", + "tooshies", + "toughies", + "townies", + "veggies", + "walkie-talkies", + "wedgies", + "weenies", + "weirdies", + "yardies", + "yuppies", + "zombies" + ); + + /** Maps irregular Germanic English plural nouns to their singular form */ + public static Map<String,String> irregular=new FinalMap<String,String>( + "beefs","beef", + "beeves","beef", + "brethren","brother", + "busses","bus", + "cattle","cattlebeast", + "children","child", + "corpora","corpus", + "ephemerides","ephemeris", + "firemen","fireman", + "genera","genus", + "genies","genie", + "genii","genie", + "kine","cow", + "lice","louse", + "men","man", + "mice","mouse", + "mongooses","mongoose", + "monies","money", + "mythoi","mythos", + "octopodes","octopus", + "octopuses","octopus", + "oxen","ox", + "people","person", + "soliloquies","soliloquy", + "throes","throes", + "trilbys","trilby", + "women","woman" + ); + + /** Contains word forms that can either be plural or singular */ + public static Set<String> singAndPlur=new FinalSet<String>( + "acoustics", + "aestetics", + "aquatics", + "basics", + "ceramics", + "classics", + "cosmetics", + "dermatoglyphics", + "dialectics", + "dynamics", + "esthetics", + "ethics", + "harmonics", + "heroics", + "isometrics", + "mechanics", + "metrics", + "statistics", + "optic", + "people", + "physics", + "polemics", + "premises", + "propaedeutics", + "pyrotechnics", + "quadratics", + "quarters", + "statistics", + "tactics", + "tropics" + ); + + /** Test routine */ + public static void main(String[] argv) throws Exception { + System.out.println("Enter an English word in plural form and press ENTER"); + BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); + while(true) { + String w=in.readLine(); + if(w.length()==0) break; + if(isPlural(w)) System.out.println("This word is plural"); + if(isSingular(w)) System.out.println("This word is singular"); + System.out.println("Stemmed to singular: "+stem(w)); + } + } +}
diff --git a/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PositionTracker.java b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PositionTracker.java new file mode 100644 index 0000000..e91c4fb --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/main/java/org/grails/datastore/gorm/neo4j/parsers/PositionTracker.java
@@ -0,0 +1,288 @@ +package org.grails.datastore.gorm.neo4j.parsers; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * This class is part of the Java Tools (see + * http://mpii.de/yago-naga/javatools). It is licensed under the Creative + * Commons Attribution License (see http://creativecommons.org/licenses/by/3.0) + * by the YAGO-NAGA team (see http://mpii.de/yago-naga). + * + * This class implements position change trackers that keep track of position + * changes within a String, e.g. caused through normalization etc. + * This allows for instance, given a position int the normalized string + * to get the corresponding position in the original non-normalized string + * + * + * + * backward position tracker - + * tracking several replacement/text changes allowing to trace a position in the modified + * text back to the corresp. position in the original text + * for the other direction see ForwardPositionTracker + * + * @author smetzger */ +public class PositionTracker { + + + private SortedMap<Integer,Integer>positionMap; + private SortedMap<Integer,Integer>positionChanges; + private SortedMap<Integer,Integer>old2NewMap; + private int accumulatedModifier=0; + + public PositionTracker(){ + positionMap=new TreeMap<Integer,Integer>(); + positionChanges=new TreeMap<Integer,Integer>(); + old2NewMap=new TreeMap<Integer,Integer>(); + } + + + public void addPositionChange(int pos, int modifier){ + if(modifier!=0){ + int oldModifier=0; + old2NewMap.put(pos, modifier); + accumulatedModifier+=modifier; + if(positionChanges.containsKey(pos+accumulatedModifier)) + oldModifier=positionChanges.get(pos+accumulatedModifier); + positionChanges.put(pos+accumulatedModifier,modifier*-1+oldModifier); + } + } + + + + /** Closes the current changing run by Merging new position changes into the existing position change map + * after each round (one round=consecutive changes along the text) you need to call closeRun() before submitting more position changes from a new round, + * i.e. whenever you passed the string to be modified once call closeRun() before starting to run over the string again with more replacements + * Do this every time you ran once over the text making changes to be tracked*/ + public void closeRun() { + if(positionChanges.isEmpty()) + return; + + + SortedMap<Integer,Integer> temp=positionChanges; + + //adapt old positions to new mapping + while(!positionMap.isEmpty()){ + Integer key=positionMap.firstKey(); + Collection<Integer> modifiers=old2NewMap.headMap(key+1).values(); + Integer newposition=key; + for(Iterator<Integer> it=modifiers.iterator(); it.hasNext(); newposition+=it.next()){} + Integer value=positionMap.get(key); + if(positionChanges.containsKey(newposition)) + value+=positionChanges.get(newposition); + positionChanges.put(newposition, value); + positionMap.remove(key); + } + + positionChanges=positionMap; + positionMap=temp; + old2NewMap.clear(); + accumulatedModifier=0; + return; + } + + + + + /** Merges new position changes (given with the inversed old2new mapping) into the existing position change map*/ +/* private void addPositionMappings(SortedMap<Integer,Integer> newPosChanges, + SortedMap<Integer,Integer> old2NewMap) { + + + TreeMap<Integer,Integer> newMap=new TreeMap<Integer,Integer>(); + + //adapt old positions to new mapping + while(!positionMap.isEmpty()){ + Integer key=positionMap.firstKey(); + Collection<Integer> modifiers=old2NewMap.headMap(key+1).values(); + Integer newposition=key; + for(Iterator<Integer> it=modifiers.iterator(); it.hasNext(); newposition+=it.next()){} + Integer value=positionMap.get(key); + if(newMap.containsKey(newposition)) + value+=newMap.get(newposition); + newMap.put(newposition, value); + positionMap.remove(key); + } + while(!newPosChanges.isEmpty()){ + Integer key=newPosChanges.firstKey(); + Integer value=newPosChanges.get(key); + if(newMap.containsKey(key)) + value+=newMap.get(key); + newMap.put(key, value); + newPosChanges.remove(key); + } + positionMap=newMap; + old2NewMap.clear(); + return; + } + */ + + public Integer translatePosition(Integer pos) { + SortedMap<Integer,Integer> headMap=positionMap.headMap(pos+1); + Integer modifier=0; + for(Iterator<Integer> it=headMap.values().iterator(); it.hasNext(); modifier+=it.next()){} +/* if(headMap.size()>1){ TODO: Possible Optimization if we assume positions are asked in ascending order + headMap.clear(); + posMap.put(pos, modifier); + }*/ + return pos+modifier; + } + + + + + + + + + + + + /** forward position change tracking - keeping track of several rounds of text modifications allowing to trace a position in the original + * text along the modifications to the corresp. position in the modified text + * after each round (one round=consecutive changes along the text) you need to call closeRun() before submitting more position changes from a new round, + * i.e. whenever you passed the string to be modified once call closeRun() before starting to run over the string again with more replacements + * REMARK: NOT TESTED WITH MORE THAN ONE ROUND! may be ERRORNOUS with multiple rounds -> use with care (works with a single round though) + * @author smetzger + * + */ + public static class ForwardPositionTracker { + + + private SortedMap<Integer,Integer>positionMap; + private SortedMap<Integer,Integer>positionChanges; + //private SortedMap<Integer,Integer>new2OldMap; + private PositionTracker new2OldTracker=null; + // private int accumulatedModifier=0; + + public ForwardPositionTracker(){ + positionMap=new TreeMap<Integer,Integer>(); + positionChanges=new TreeMap<Integer,Integer>(); + // new2OldMap=new TreeMap<Integer,Integer>(); + new2OldTracker=new PositionTracker(); + + } + + + public void addPositionChange(int pos, int modifier){ + if(modifier!=0){ + positionChanges.put(pos,modifier); + // accumulatedModifier+=modifier; + /*if(new2OldMap.containsKey(pos+accumulatedModifier)) + oldModifier=new2OldMap.get(pos+accumulatedModifier); + new2OldMap.put(pos+accumulatedModifier, -1*modifier+oldModifier); + } */ + new2OldTracker.addPositionChange(pos, modifier); + } + } + + + + + + + + /** Closes the current changing run by Merging new position changes into the existing position change map + * Do this every time you ran once over the text making changes to be tracked*/ + public void closeRun() { + if(positionChanges.isEmpty()) + return; + + + for(Map.Entry<Integer, Integer> change:positionChanges.entrySet()){ + Integer positionInOrigStream=new2OldTracker.translatePosition(change.getKey()); + if(positionMap.containsKey(positionInOrigStream)) + positionMap.put(positionInOrigStream, change.getValue()+positionMap.get(positionInOrigStream)); + else + positionMap.put(positionInOrigStream, change.getValue()); + } + + positionChanges.clear(); +// accumulatedModifier=0; + new2OldTracker.closeRun(); + + return; + } + + + + /** tells whether a position in the original stream has been cut away by some change operation, + * such that translating it usually would make not to much sense + * @return true, iff the given position has been cut away, false otherwise (i.e. false if it should be mappable) + * TODO: current version ONLY WORKS SECURELY WHEN THERE IS ONLY ONE POSITION CHANGE RUN WITHOUT OVERLAPPING CHANGES! + * as soon as there are more than one change runs, or changes that overlap, we would need to check all following changes instead of only the next one */ + public boolean hasBeenCutAway(Integer pos){ + SortedMap<Integer,Integer> tailMap=positionMap.tailMap(pos+1); + if(tailMap.isEmpty()) + return false; + Integer key=tailMap.firstKey(); + Integer modifier=tailMap.get(key); + if(modifier<0 && key+modifier<=pos ) + return true; + else + return false; + /* this does not work for the general case (had it the wrong way aroung), but can be used to implement it + Integer key=null; + Iterator<Integer> it=tailMap.keySet().iterator(); + while(it.hasNext()){ + key=it.next(); + Integer mod=tailMap.get(key); + if(mod<0 && key-mod>=pos) + return true; + } + return false;*/ + } + + public Integer translatePosition(Integer pos) { + SortedMap<Integer,Integer> headMap=positionMap.headMap(pos+1); + Integer modifier=0; + for(Iterator<Integer> it=headMap.values().iterator(); it.hasNext(); modifier+=it.next()){} + /* if(headMap.size()>1){ Optimization if we assume positions are asked in ascending order + headMap.clear(); + posMap.put(pos, modifier); + }*/ + return pos+modifier; + } + + /** also handles positions inside text parts that have been cut out properly + * + * TODO: current version ONLY WORKS SECURELY WHEN THERE IS ONLY ONE POSITION CHANGE RUN WITHOUT OVERLAPPING CHANGES! + * as soon as there are more than one change runs, or changes that overlap, we would need to check all following changes instead of only the next one */ + public Integer translatePositionExactly(Integer pos) { + + SortedMap<Integer,Integer> tailMap=positionMap.tailMap(pos+1); + if(tailMap.isEmpty()) + return translatePosition(pos); + else{ + Integer key=tailMap.firstKey(); + Integer modifier=tailMap.get(key); + return translatePosition(Math.min(pos,key+modifier)); + } + +/* + * That version does it the wrong way around + * SortedMap<Integer,Integer> headMap=positionMap.headMap(pos+1); + Integer modifier=0; + Integer key=null, value=null; + Iterator<Integer> it=headMap.keySet().iterator(); + while(it.hasNext()){ + key=it.next(); + value=headMap.get(key); + if(value<0) + modifier+=Math.max(key-pos, value); + }*/ + /* if(headMap.size()>1){ Optimization if we assume positions are asked in ascending order + headMap.clear(); + posMap.put(pos, modifier); + } + return pos+modifier; */ + + } + + } + + +}
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/CascadingDeleteSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/CascadingDeleteSpec.groovy index efbbb87..681af0e 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/CascadingDeleteSpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/CascadingDeleteSpec.groovy
@@ -3,7 +3,6 @@ import grails.gorm.DetachedCriteria import org.slf4j.Logger import org.slf4j.LoggerFactory -import spock.lang.Ignore class CascadingDeleteSpec extends GormDatastoreSpec { @@ -72,7 +71,7 @@ then: def criteria = new DetachedCriteria(Club).build {} - criteria.deleteAll() + criteria.deleteAll() then: Club.count() == 0
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/LabelStrategySpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/LabelStrategySpec.groovy index 22b73ab..12e3433 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/LabelStrategySpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/LabelStrategySpec.groovy
@@ -1,11 +1,13 @@ package grails.gorm.tests +import grails.gorm.dirty.checking.DirtyCheck import grails.persistence.Entity import org.grails.datastore.gorm.Setup import org.grails.datastore.gorm.neo4j.GraphPersistentEntity import org.grails.datastore.mapping.core.Session import org.neo4j.graphdb.DynamicLabel import org.neo4j.helpers.collection.IteratorUtil +import spock.lang.Issue /** * test for various strategies to define Neo4j labels on domain classes and instances @@ -23,8 +25,12 @@ } public class LocalSetup extends Setup { + @Override static Session setup(classes) { skipIndexSetup = false + extendedValidatorSetup = { mappingContext, grailsApplication -> + setupValidator(mappingContext, grailsApplication, InstanceDependentLabels.simpleName) + } Setup.setup(classes) } } @@ -65,7 +71,13 @@ labels.every { Setup.graphDb.schema().getIndexes(DynamicLabel.label(it))*.propertyKeys == [['__id__']] } - } + + when: + def d = StaticLabels.findByName("dummy") + + then: + d!=null + d.id == s.id} def "should dynamic label mapping work"() { when: @@ -73,6 +85,13 @@ then: verifyLabelsForId(s.id, [s.class.name]) + + when: + def d = DynLabel.findByName("dummy") + + then: + d!=null + d.id == s.id } def "should mixed labels mapping work"() { @@ -80,15 +99,26 @@ def s = new MixedLabels(name:'dummy').save(flush:true) then: - verifyLabelsForId(s.id, ["MyLabel", s.class.name]) - } + verifyLabelsForId(s.id, ["MixedLabel", s.class.name]) - def "should instance dependent labels mapping work"() { when: - def s = new InstanceDependentLabels(name:'Sam', profession: 'Fireman').save(flush:true) + def d = MixedLabels.findByName("dummy") then: - verifyLabelsForId(s.id, ["MyLabel", "${s.name}"]) + d!=null + d.id == s.id + } + + @Issue("https://jira.grails.org/browse/GPNEO4J-17") + def "should instance dependent labels mapping work"() { + + when: + def s = new InstanceDependentLabels(name:'Sam', profession: 'Fireman') + s.save(flush:true) + + then: + s.hasErrors() == false + verifyLabelsForId(s.id, ["InstanceDependentLabels", "${s.profession}"]) and: Setup.graphDb.schema().getIndexes(DynamicLabel.label("MyLabel"))*.propertyKeys == [['__id__']] @@ -98,6 +128,24 @@ and: "there are no indexes on null" Setup.graphDb.schema().getIndexes().every { it.label.name() != 'null'} + + when: "create Sam again, now as policeman" + def d = new InstanceDependentLabels(name:'Sam', profession: 'Policeman') + d.save(flush:true) + + then: "we've violated unique constraint" + d.hasErrors() == true + d.errors.allErrors[0].code == "unique" + d.errors + + when: "unmarshall Sam instance" + def sam = InstanceDependentLabels.findByName("Sam") + + then: + sam != null + sam.profession == "Fireman" + s.id == sam.id + } private def verifyLabelsForId(id, labelz) { @@ -107,6 +155,7 @@ } } +@DirtyCheck @Entity class Default { Long id @@ -114,17 +163,7 @@ String name } -@Entity -class StaticLabel { - Long id - Long version - String name - - static mapping = { - labels "MyLabel" - } -} - +@DirtyCheck @Entity class StaticLabels { Long id @@ -137,6 +176,19 @@ } +@DirtyCheck +@Entity +class StaticLabel { + Long id + Long version + String name + + static mapping = { + labels "MyLabel" + } +} + +@DirtyCheck @Entity class DynLabel { Long id @@ -148,6 +200,7 @@ } } +@DirtyCheck @Entity class MixedLabels { Long id @@ -155,11 +208,11 @@ String name static mapping = { - labels "MyLabel", { GraphPersistentEntity pe -> "`${pe.javaClass.name}`" } + labels "MixedLabel", { GraphPersistentEntity pe -> "`${pe.javaClass.name}`" } } } - +@DirtyCheck @Entity class InstanceDependentLabels { Long id @@ -171,8 +224,8 @@ name unique:true } static mapping = { - labels "MyLabel", { GraphPersistentEntity pe, instance -> // 2 arguments: instance dependent label - "`${instance.name}`" + labels { GraphPersistentEntity pe, instance -> // 2 arguments: instance dependent label + "`${instance.profession}`" } } } \ No newline at end of file
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/ManyToManySpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/ManyToManySpec.groovy index fdc9f6e..b44d836 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/ManyToManySpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/ManyToManySpec.groovy
@@ -2,8 +2,10 @@ import grails.gorm.dirty.checking.DirtyCheck import grails.persistence.Entity +import org.neo4j.helpers.collection.IteratorUtil import org.slf4j.Logger import org.slf4j.LoggerFactory +import spock.lang.Issue class ManyToManySpec extends GormDatastoreSpec { @@ -11,7 +13,7 @@ @Override List getDomainClasses() { - [Role, User, MBook, MBookworm] + [Role, User, MBook, MBookworm, BidirectionalFriends] } /*def setupSpec() { @@ -204,6 +206,34 @@ } + @Issue("GPNEO4J-20") + def "should version not increase when adding relationships"() { + setup: + def felix = new BidirectionalFriends(name: 'felix').save(flush: true) + session.clear() + + when: "adding 100 people being friend with felix" + (0..<100).each { + new BidirectionalFriends(name: "buddy$it", friends: [felix]).save() + } + session.flush() + session.clear() + def fetchedFelix = BidirectionalFriends.findByName("felix") + + then: + fetchedFelix.version == felix.version + +// and: "inverse side has correct number of friends" +// fetchedFelix.friends.size() == 100 // TODO: investigate why this domain class is not bidirectional + + when: "we have 100 relationships" + def result = session.nativeInterface.execute("MATCH (:BidirectionalFriends {name:{1}})-[:FRIENDS]-(o) return count(o) as c", ["felix"]) + + then: + IteratorUtil.single(result)["c"] == 100 + + } + } @DirtyCheck @@ -299,3 +329,15 @@ return "Bookworm: [name: ${this.name}, favoriteBook: ${this.favoriteBook?.name}]" } } + +@DirtyCheck +@Entity +class BidirectionalFriends { + Long id + Long version + String name + Set friends + + static hasMany = [ friends: BidirectionalFriends ] + static mappedBy = [ friends: "friends" ] +}
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/MiscSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/MiscSpec.groovy index b0c2377..5dd0bb3 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/MiscSpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/MiscSpec.groovy
@@ -1,5 +1,6 @@ package grails.gorm.tests +import grails.gorm.dirty.checking.DirtyCheck import grails.persistence.Entity import groovy.beans.Bindable import groovyx.gpars.GParsPool @@ -389,6 +390,33 @@ c.save(flush: true) } + def "changing one2many is consistent"() { + setup: + def argentina = new Team(name: 'Argentina').save() + def germany = new Team(name: 'Germany').save() + session.flush() + session.clear() + + when: "by error we put Manual Neuer to Argentina" + def manuel = new Player(name: 'Manuel Neuer', team: argentina).save(flush:true) + + then: + Team.findByName('Argentina').players.size()==1 + + when: + session.flush() + session.clear() + manuel = Player.findByName('Manuel Neuer') + manuel.team = germany + manuel.save() + + session.flush() + session.clear() + + then: + Team.findByName('Germany').players.size()==1 + Team.findByName('Argentina').players.size()==0 + } } @Entity @@ -405,12 +433,15 @@ @Bindable @Entity +@DirtyCheck class Team implements Serializable { Long id Long version String name Club club byte[] binaryData + Set players + static hasMany = [players: Player] static belongsTo = Club } @@ -428,4 +459,13 @@ throws ObjectStreamException { return get(id) } +} + +@Entity +@DirtyCheck +class Player { + Long id + Long version + String name + Team team } \ No newline at end of file
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/Neo4jEntityPersisterSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/Neo4jEntityPersisterSpec.groovy new file mode 100644 index 0000000..5aae270 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/Neo4jEntityPersisterSpec.groovy
@@ -0,0 +1,31 @@ +package grails.gorm.tests + +import org.grails.datastore.gorm.neo4j.Neo4jEntityPersister +import spock.lang.Specification + +/** + * @author Stefan Armbruster + */ +class Neo4jEntityPersisterSpec extends Specification { + + def "verify singular detection"() { + setup: + def cut = new Neo4jEntityPersister(null, null, null, null) + + expect: + cut.isSingular(term) == result + + where: + term | result + "word" | true + "words" | false + "friend" | true + "friends" | false + "buddy" | true + "buddies" | false + "child" | true + "children" | false + "person" | true + //"people" | false + } +}
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/NonDeclaredPropertiesSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/NonDeclaredPropertiesSpec.groovy index 88ebcfd..25ef5a9 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/NonDeclaredPropertiesSpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/NonDeclaredPropertiesSpec.groovy
@@ -1,10 +1,10 @@ package grails.gorm.tests import org.grails.datastore.gorm.neo4j.Neo4jGormEnhancer +import org.neo4j.helpers.collection.IteratorUtil import org.slf4j.Logger import org.slf4j.LoggerFactory -import spock.lang.Ignore -import spock.lang.IgnoreRest +import spock.lang.Issue class NonDeclaredPropertiesSpec extends GormDatastoreSpec { @@ -141,8 +141,52 @@ then: person.notDeclaredProperty == null + } + @Issue("GPNEO4J-25") + def "dynamic properties point to domain classes instance should be relationships"() { + setup: + def cosima = new Pet(name: 'Cosima') + def lara = new Pet(name: 'Lara') + cosima.buddy = lara + cosima.buddies = lara // NB plural version + cosima.save() + session.flush() + session.clear() + + when: + def result = session.nativeInterface.execute("MATCH (n:Pet {__id__:{1}})-[:buddy]->(l) return l", [cosima.id]) + + then: + IteratorUtil.count(result) == 1 + + and: "reading dynamic rels works" + Pet.findByName("Cosima").buddy.name == "Lara" + + and: "using plural named properties returns an array" + Pet.findByName("Cosima").buddies*.name == ["Lara"] + } + + def "dynamic properties pointing to arrays of domain classes should be a relationship"() { + setup: + def cosima = new Pet(name: 'Cosima') + def lara = new Pet(name: 'Lara') + def samira = new Pet(name: 'Samira') + cosima.buddies = [lara, samira] + + cosima.save() + session.flush() + session.clear() + + when: + def result = session.nativeInterface.execute("MATCH (n:Pet {__id__:{1}})-[:buddies]->(l) return l", [cosima.id]) + + then: + IteratorUtil.count(result) == 2 + + and: "reading dynamic rels works" + Pet.findByName("Cosima").buddies*.name == ["Lara", "Samira"] } }
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy new file mode 100644 index 0000000..9eafe32 --- /dev/null +++ b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy
@@ -0,0 +1,18 @@ +package grails.gorm.tests + +import spock.lang.Ignore +import spock.lang.Specification + +@Ignore("TODO: Neo4J association proxy support is broken after GPNEO4J-25 changes") +class UpdateWithProxyPresentSpec extends Specification { + + void "Test update entity with association proxies"() { + expect: + 1==0 + } + + void "Test update unidirectional oneToMany with proxy"() { + expect: + 1==0 + } +}
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/Setup.groovy index 0d4b0d6..3b7a272 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/Setup.groovy
@@ -1,13 +1,13 @@ package org.grails.datastore.gorm -import grails.gorm.tests.Role +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication import org.apache.tomcat.jdbc.pool.DataSource import org.apache.tomcat.jdbc.pool.PoolProperties -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator import org.grails.datastore.gorm.events.AutoTimestampEventListener import org.grails.datastore.gorm.events.DomainEventListener import org.grails.datastore.gorm.neo4j.DumpGraphOnSessionFlushListener +import org.grails.datastore.gorm.neo4j.HashcodeEqualsAwareProxyFactory import org.grails.datastore.gorm.neo4j.Neo4jDatastore import org.grails.datastore.gorm.neo4j.Neo4jGormEnhancer import org.grails.datastore.gorm.neo4j.Neo4jMappingContext @@ -17,6 +17,7 @@ import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.transactions.DatastoreTransactionManager +import org.grails.validation.GrailsDomainClassValidator import org.neo4j.graphdb.GraphDatabaseService import org.neo4j.kernel.GraphDatabaseAPI import org.neo4j.kernel.impl.transaction.TxManager @@ -41,6 +42,7 @@ static DataSource dataSource static WebServer webServer static skipIndexSetup = true + static Closure extendedValidatorSetup = null static destroy() { dataSource.close() @@ -99,40 +101,21 @@ new JdbcCypherEngine(dataSource) ) datastore.skipIndexSetup = skipIndexSetup - //datastore.mappingContext.proxyFactory = new GroovyProxyFactory() + datastore.mappingContext.proxyFactory = new HashcodeEqualsAwareProxyFactory() + +// ConstrainedProperty.registerNewConstraint(UniqueConstraint.UNIQUE_CONSTRAINT, UniqueConstraint) for (Class cls in classes) { mappingContext.addPersistentEntity(cls) } - PersistentEntity entity = mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} + def grailsApplication = new DefaultGrailsApplication(classes as Class[], Setup.getClassLoader()) + grailsApplication.mainContext = ctx + grailsApplication.initialise() - mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - entity = mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("Role")} - if (entity) { - - def grailsApplication = new DefaultGrailsApplication([Role] as Class[], Setup.getClassLoader()) - grailsApplication.mainContext = ctx - grailsApplication.initialise() - - def validator = new GrailsDomainClassValidator( - grailsApplication: grailsApplication, - domainClass: grailsApplication.getDomainClass(entity.name) - ) - - datastore.mappingContext.addEntityValidator(entity, validator) - } + setupValidators(mappingContext, grailsApplication) def enhancer = new Neo4jGormEnhancer(datastore, new DatastoreTransactionManager(datastore: datastore)) -// def enhancer = new GormEnhancer(datastore, new DatastoreTransactionManager(datastore: datastore)) enhancer.enhance() datastore.afterPropertiesSet() @@ -147,14 +130,43 @@ ctx.addApplicationListener new DomainEventListener(datastore) ctx.addApplicationListener new AutoTimestampEventListener(datastore) -// // enable for debugging -// if (graphDb) { -// ctx.addApplicationListener new DumpGraphOnSessionFlushListener(graphDb) -// } + // enable for debugging + if (graphDb) { + ctx.addApplicationListener new DumpGraphOnSessionFlushListener(graphDb) + } datastore.connect() } + static void setupValidators(MappingContext mappingContext, GrailsApplication grailsApplication) { + + setupValidator(mappingContext, grailsApplication, "TestEntity", [ + supports: { Class c -> true }, + validate: { o, Errors errors -> + if (!StringUtils.hasText(o.name)) { + errors.rejectValue("name", "name.is.blank") + } + } + ] as Validator) + + setupValidator(mappingContext, grailsApplication, "Role") + + if (extendedValidatorSetup) { + extendedValidatorSetup(mappingContext, grailsApplication) + } + } + + static void setupValidator(MappingContext mappingContext, GrailsApplication grailsApplication, String entityName, Validator validator = null) { + PersistentEntity entity = mappingContext.persistentEntities.find { PersistentEntity e -> e.javaClass.simpleName == entityName } + if (entity) { + mappingContext.addEntityValidator(entity, validator ?: + new GrailsDomainClassValidator( + grailsApplication: grailsApplication, + domainClass: grailsApplication.getDomainClass(entity.javaClass.name) + ) ) + } + } + private static void waitForIndexesBeingOnline(GraphDatabaseService graphDb) { if (graphDb && (skipIndexSetup==false)) { def tx = graphDb.beginTx()
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/Neo4jSuite.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/Neo4jSuite.groovy index 48c4a29..ddb7d2b 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/Neo4jSuite.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/Neo4jSuite.groovy
@@ -56,7 +56,8 @@ //ApiExtensionsSpec, //RelationshipUtilsSpec, //CascadingDeleteSpec, -//NonDeclaredPropertiesSpec +//NonDeclaredPropertiesSpec, +//LabelStrategySpec, ]) class Neo4jSuite {
diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurerSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurerSpec.groovy index c4b24d3..810b7cb 100644 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurerSpec.groovy +++ b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurerSpec.groovy
@@ -1,12 +1,11 @@ package org.grails.datastore.gorm.neo4j.plugin.support +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication import grails.gorm.tests.Person +import grails.plugins.DefaultGrailsPluginManager import grails.spring.BeanBuilder -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.plugins.DefaultGrailsPluginManager - +import org.grails.core.artefact.DomainClassArtefactHandler import spock.lang.Specification /**
diff --git a/grails-datastore-gorm-plugin-support/build.gradle b/grails-datastore-gorm-plugin-support/build.gradle index 8518ca1..8c2c1fa 100644 --- a/grails-datastore-gorm-plugin-support/build.gradle +++ b/grails-datastore-gorm-plugin-support/build.gradle
@@ -17,6 +17,7 @@ exclude group:'oro',module:'oro' exclude group:'asm',module:'asm' exclude group:'cglib',module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'xalan',module:'serializer' exclude group:'org.springframework',module:'spring-aspects' exclude group:'org.springframework',module:'spring-beans'
diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/AggregatePersistenceContextInterceptor.java b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/AggregatePersistenceContextInterceptor.java index 815308a..f291e85 100644 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/AggregatePersistenceContextInterceptor.java +++ b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/AggregatePersistenceContextInterceptor.java
@@ -15,9 +15,10 @@ */ package org.grails.datastore.gorm.plugin.support; +import grails.persistence.support.PersistenceContextInterceptor; + import java.util.List; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; /** * @author Graeme Rocher
diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandler.groovy b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandler.groovy index bac2bd4..9b18f58 100644 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandler.groovy +++ b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandler.groovy
@@ -14,13 +14,14 @@ */ package org.grails.datastore.gorm.plugin.support +import grails.core.GrailsServiceClass +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.core.artefact.ServiceArtefactHandler +import org.grails.spring.TypeSpecifyableTransactionProxyFactoryBean +import org.grails.transaction.GroovyAwareNamedTransactionAttributeSource + import java.lang.reflect.Method -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsServiceClass -import org.codehaus.groovy.grails.commons.ServiceArtefactHandler -import org.codehaus.groovy.grails.commons.spring.TypeSpecifyableTransactionProxyFactoryBean -import org.codehaus.groovy.grails.orm.support.GroovyAwareNamedTransactionAttributeSource import org.grails.datastore.mapping.core.Datastore import org.springframework.context.ApplicationContext import org.springframework.core.annotation.AnnotationUtils @@ -66,7 +67,7 @@ return } - def beans = plugin.beans { + plugin.beans { def scope = serviceClass.getPropertyValue("scope") def props = ["*": "PROPAGATION_REQUIRED"] as Properties "${serviceClass.propertyName}"(TypeSpecifyableTransactionProxyFactoryBean, serviceClass.clazz) { bean -> @@ -83,7 +84,6 @@ delegate.transactionManager = ref("${datastoreType.toLowerCase()}TransactionManager") } } - beans.registerBeans(event.ctx) } }
diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy index d804279..03ce794 100644 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy +++ b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy
@@ -62,7 +62,7 @@ registry.getBeanDefinitionNames().findAll { String beanName -> beanName ==~ persistenceInterceptorBeanNamePattern } } - protected ManagedList moveInterceptorBeansToManagedList(BeanDefinitionRegistry registry, Collection persistenceInterceptorBeanNames) { + protected ManagedList moveInterceptorBeansToManagedList(BeanDefinitionRegistry registry, Collection<String> persistenceInterceptorBeanNames) { ManagedList list = new ManagedList() persistenceInterceptorBeanNames.each { String beanName -> list.add registry.getBeanDefinition(beanName)
diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurer.groovy b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurer.groovy index 36df01e..d22fad1 100644 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurer.groovy +++ b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurer.groovy
@@ -15,11 +15,12 @@ package org.grails.datastore.gorm.plugin.support +import grails.core.GrailsDomainClassProperty +import grails.core.GrailsServiceClass +import org.grails.validation.GrailsDomainClassValidator + import java.lang.reflect.Method -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.commons.GrailsServiceClass -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator import org.grails.datastore.gorm.support.DatastorePersistenceContextInterceptor import org.grails.datastore.mapping.reflect.ClassPropertyFetcher import org.grails.datastore.mapping.transactions.DatastoreTransactionManager
diff --git a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurerSpec.groovy b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurerSpec.groovy index 11d254a..9949e57 100644 --- a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurerSpec.groovy +++ b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurerSpec.groovy
@@ -2,8 +2,8 @@ import grails.persistence.Entity import grails.validation.ValidationException +import grails.validation.ConstrainedProperty import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.simple.SimpleMapDatastore import org.grails.datastore.mapping.transactions.DatastoreTransactionManager
diff --git a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregatorSpec.groovy b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregatorSpec.groovy index a9b8ab3..639fecc 100644 --- a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregatorSpec.groovy +++ b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregatorSpec.groovy
@@ -15,9 +15,9 @@ package org.grails.datastore.gorm.plugin.support +import grails.persistence.support.PersistenceContextInterceptor import grails.spring.BeanBuilder -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor import org.springframework.context.ApplicationContext import spock.lang.Specification
diff --git a/grails-datastore-gorm-redis/build.gradle b/grails-datastore-gorm-redis/build.gradle index 0ee03be..bdea4fb 100644 --- a/grails-datastore-gorm-redis/build.gradle +++ b/grails-datastore-gorm-redis/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.1.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies {
diff --git a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy index ef7165b..93ba059 100644 --- a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy
@@ -1,9 +1,9 @@ package grails.gorm.tests import grails.persistence.Entity +import grails.validation.ConstrainedProperty import groovy.transform.NotYetImplemented -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import org.grails.core.support.GrailsDomainConfigurationUtil import org.grails.datastore.gorm.validation.constraints.UniqueConstraint import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity
diff --git a/grails-datastore-gorm-rest-client/build.gradle b/grails-datastore-gorm-rest-client/build.gradle index fbd7c79..c19f9b0 100644 --- a/grails-datastore-gorm-rest-client/build.gradle +++ b/grails-datastore-gorm-rest-client/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies { compile 'javax.servlet:javax.servlet-api:3.0.1' runtime "org.springframework:spring-webmvc:$springVersion"
diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormInstanceApi.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormInstanceApi.groovy index ddef3d7..c965c92 100644 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormInstanceApi.groovy +++ b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormInstanceApi.groovy
@@ -17,13 +17,13 @@ import org.grails.datastore.gorm.GormInstanceApi import org.grails.datastore.mapping.core.Datastore -import org.codehaus.groovy.grails.plugins.converters.api.ConvertersApi import org.grails.datastore.mapping.rest.client.RestClientSession import groovy.transform.CompileStatic import grails.plugins.rest.client.RequestCustomizer import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.core.SessionCallback import groovy.transform.TypeCheckingMode +import org.grails.plugins.converters.api.ConvertersApi /** * Extensions to the instance API for REST
diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientDatastore.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientDatastore.groovy index 4bd125a..d0f6bf8 100644 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientDatastore.groovy +++ b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientDatastore.groovy
@@ -18,8 +18,6 @@ import grails.plugins.rest.client.async.AsyncRestBuilder import grails.rest.render.RendererRegistry import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.binding.bindingsource.DataBindingSourceRegistry -import org.codehaus.groovy.grails.web.binding.bindingsource.DefaultDataBindingSourceRegistry import org.grails.datastore.mapping.cache.TPCacheAdapterRepository import org.grails.datastore.mapping.core.AbstractDatastore import org.grails.datastore.mapping.core.Session @@ -28,6 +26,8 @@ import org.grails.datastore.mapping.rest.client.config.RestClientMappingContext import org.grails.datastore.mapping.rest.client.http.converters.PersistentEntityHttpConverter import org.grails.plugins.web.rest.render.DefaultRendererRegistry +import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry +import org.grails.web.databinding.bindingsource.DefaultDataBindingSourceRegistry import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ConfigurableApplicationContext import org.springframework.web.client.RestTemplate @@ -55,11 +55,11 @@ String baseUrl = DEFAULT_BASE_URL - Map<PersistentEntity, AsyncRestBuilder> asyncRestClients = new ConcurrentHashMap<>().withDefault { PersistentEntity entity -> + Map<PersistentEntity, AsyncRestBuilder> asyncRestClients = new ConcurrentHashMap<PersistentEntity, AsyncRestBuilder>().withDefault { PersistentEntity entity -> new AsyncRestBuilder(syncRestClients.get(entity)) } - Map<PersistentEntity, RestBuilder> syncRestClients = new ConcurrentHashMap<>().withDefault { PersistentEntity entity -> + Map<PersistentEntity, RestBuilder> syncRestClients = new ConcurrentHashMap<PersistentEntity, RestBuilder>().withDefault { PersistentEntity entity -> final template = new RestTemplate(((Endpoint) entity.mapping.mappedForm).httpRequestFactory) final converters = template.getMessageConverters() converters.add(new PersistentEntityHttpConverter<Object>(entity, rendererRegistry, bindingSourceRegistry))
diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/engine/RestClientEntityPersister.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/engine/RestClientEntityPersister.groovy index 01ff64f..27fc49b 100644 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/engine/RestClientEntityPersister.groovy +++ b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/engine/RestClientEntityPersister.groovy
@@ -16,14 +16,15 @@ import grails.async.Promise import grails.async.PromiseList +import grails.core.GrailsDomainClassProperty +import grails.databinding.DataBindingSource import grails.plugins.rest.client.RestBuilder import grails.plugins.rest.client.RestResponse import grails.plugins.rest.client.async.AsyncRestBuilder import grails.util.GrailsNameUtils +import grails.web.databinding.DataBindingUtils +import grails.web.mime.MimeType import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.binding.DataBindingUtils -import org.codehaus.groovy.grails.web.mime.MimeType -import org.grails.databinding.DataBindingSource import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.core.SessionImplementor import org.grails.datastore.mapping.dirty.checking.DirtyCheckable @@ -43,7 +44,6 @@ import org.grails.datastore.mapping.core.impl.PendingInsertAdapter import org.grails.datastore.mapping.rest.client.RestClientException import org.grails.datastore.mapping.rest.client.RestClientSession -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty import org.grails.datastore.mapping.rest.client.query.RequestParameterRestClientQuery /**
diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityHttpConverter.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityHttpConverter.groovy index a40625c..cbd8e7d 100644 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityHttpConverter.groovy +++ b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityHttpConverter.groovy
@@ -16,12 +16,12 @@ import grails.rest.render.RendererRegistry import grails.util.GrailsNameUtils +import grails.web.databinding.DataBindingUtils +import grails.web.mime.MimeType import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.binding.DataBindingUtils -import org.codehaus.groovy.grails.web.binding.bindingsource.DataBindingSourceRegistry -import org.codehaus.groovy.grails.web.mime.MimeType import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.rest.client.config.Endpoint +import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry import org.springframework.http.HttpInputMessage import org.springframework.http.HttpMethod import org.springframework.http.HttpOutputMessage
diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityListHttpConverter.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityListHttpConverter.groovy index 4040e7d..982553f 100644 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityListHttpConverter.groovy +++ b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityListHttpConverter.groovy
@@ -15,11 +15,11 @@ package org.grails.datastore.mapping.rest.client.http.converters import grails.rest.render.RendererRegistry +import grails.web.databinding.DataBindingUtils +import grails.web.mime.MimeType import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.binding.DataBindingUtils -import org.codehaus.groovy.grails.web.binding.bindingsource.DataBindingSourceRegistry -import org.codehaus.groovy.grails.web.mime.MimeType import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry import org.springframework.http.HttpInputMessage import org.springframework.http.HttpOutputMessage import org.springframework.http.MediaType
diff --git a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/RestClientDatastoreSpec.groovy b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/RestClientDatastoreSpec.groovy index d535097..64ccdab 100644 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/RestClientDatastoreSpec.groovy +++ b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/RestClientDatastoreSpec.groovy
@@ -1,9 +1,6 @@ package org.grails.datastore.gorm.rest.client -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationHolder -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationInitializer - +import grails.core.DefaultGrailsApplication import org.grails.datastore.gorm.events.AutoTimestampEventListener import org.grails.datastore.gorm.events.DomainEventListener import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer @@ -12,6 +9,8 @@ import org.grails.datastore.mapping.rest.client.RestClientDatastore import org.grails.datastore.mapping.rest.client.RestClientSession import org.grails.datastore.mapping.transactions.DatastoreTransactionManager +import org.grails.web.converters.configuration.ConvertersConfigurationHolder +import org.grails.web.converters.configuration.ConvertersConfigurationInitializer import org.springframework.context.support.GenericApplicationContext import spock.lang.Shared import spock.lang.Specification @@ -28,7 +27,7 @@ void setupSpec() { final application = new DefaultGrailsApplication(getDomainClasses() as Class[], new GroovyClassLoader()) application.initialise() - new ConvertersConfigurationInitializer().initialize(application) + new ConvertersConfigurationInitializer(grailsApplication: application).initialize() def applicationContext = new GenericApplicationContext() applicationContext.refresh()
diff --git a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/CrudJsonSpec.groovy b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/CrudJsonSpec.groovy index bdfdfc0..9a4717b 100644 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/CrudJsonSpec.groovy +++ b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/CrudJsonSpec.groovy
@@ -1,10 +1,7 @@ package org.grails.datastore.gorm.rest.client.json import grails.persistence.Entity -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationHolder -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationInitializer -import org.codehaus.groovy.grails.web.servlet.HttpHeaders +import grails.web.http.HttpHeaders import org.springframework.http.HttpMethod import org.springframework.http.MediaType import org.springframework.test.web.client.MockRestServiceServer
diff --git a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/DirtyCheckingSpec.groovy b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/DirtyCheckingSpec.groovy index 6906e28..2ef3ef3 100644 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/DirtyCheckingSpec.groovy +++ b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/DirtyCheckingSpec.groovy
@@ -2,7 +2,7 @@ import grails.gorm.dirty.checking.DirtyCheck import grails.persistence.Entity -import org.codehaus.groovy.grails.web.servlet.HttpHeaders +import grails.web.http.HttpHeaders import org.grails.datastore.gorm.rest.client.RestClientDatastoreSpec import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import org.springframework.http.HttpMethod
diff --git a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/xml/CrudXmlSpec.groovy b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/xml/CrudXmlSpec.groovy index c3bb399..1ab4029 100644 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/xml/CrudXmlSpec.groovy +++ b/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/xml/CrudXmlSpec.groovy
@@ -1,7 +1,7 @@ package org.grails.datastore.gorm.rest.client.xml import grails.persistence.Entity -import org.codehaus.groovy.grails.web.servlet.HttpHeaders +import grails.web.http.HttpHeaders import org.grails.datastore.gorm.rest.client.RestClientDatastoreSpec import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus
diff --git a/grails-datastore-gorm-riak/build.gradle b/grails-datastore-gorm-riak/build.gradle index 53bc22a..eec4214 100644 --- a/grails-datastore-gorm-riak/build.gradle +++ b/grails-datastore-gorm-riak/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails
diff --git a/grails-datastore-gorm-simpledb/build.gradle b/grails-datastore-gorm-simpledb/build.gradle index bec152f..fb7df6b 100644 --- a/grails-datastore-gorm-simpledb/build.gradle +++ b/grails-datastore-gorm-simpledb/build.gradle
@@ -1,4 +1,4 @@ -version = "0.6.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails
diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/EnumSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/EnumSpec.groovy index d3aedc9..d3d40cf 100644 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/EnumSpec.groovy +++ b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/EnumSpec.groovy
@@ -3,6 +3,7 @@ import grails.persistence.Entity import org.grails.datastore.mapping.core.Session +import spock.lang.IgnoreRest import spock.lang.Issue class EnumSpec extends GormDatastoreSpec {
diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy index 2c7f6f2..81137cd 100644 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy
@@ -1,9 +1,8 @@ package grails.gorm.tests import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import grails.validation.ConstrainedProperty +import org.grails.core.support.GrailsDomainConfigurationUtil import org.grails.datastore.gorm.validation.constraints.UniqueConstraint import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity
diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/persistence/Entity.java b/grails-datastore-gorm-tck/src/main/groovy/grails/persistence/Entity.java deleted file mode 100644 index 725fbaf..0000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,15 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Entity { -}
diff --git a/grails-datastore-gorm-test/src/main/groovy/grails/datastore/test/DatastoreUnitTestMixin.groovy b/grails-datastore-gorm-test/src/main/groovy/grails/datastore/test/DatastoreUnitTestMixin.groovy index 36c024e..e476432 100644 --- a/grails-datastore-gorm-test/src/main/groovy/grails/datastore/test/DatastoreUnitTestMixin.groovy +++ b/grails-datastore-gorm-test/src/main/groovy/grails/datastore/test/DatastoreUnitTestMixin.groovy
@@ -14,13 +14,10 @@ */ package grails.datastore.test -import grails.test.MockUtils - -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass -import org.codehaus.groovy.grails.plugins.DefaultGrailsPluginManager -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.codehaus.groovy.grails.plugins.PluginManagerHolder -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator +import grails.plugins.DefaultGrailsPluginManager +import grails.plugins.GrailsPluginManager +import grails.util.Holders +import org.grails.core.DefaultGrailsDomainClass import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.events.AutoTimestampEventListener import org.grails.datastore.gorm.events.DomainEventListener @@ -29,6 +26,7 @@ import org.grails.datastore.mapping.simple.SimpleMapDatastore import org.grails.datastore.mapping.transactions.DatastoreTransactionManager import org.grails.datastore.mapping.transactions.SessionHolder +import org.grails.validation.GrailsDomainClassValidator import org.springframework.context.ConfigurableApplicationContext import org.springframework.context.support.GenericApplicationContext import org.springframework.transaction.PlatformTransactionManager @@ -92,14 +90,13 @@ } } - if (!(PluginManagerHolder.pluginManager instanceof DefaultGrailsPluginManager)) { - PluginManagerHolder.pluginManager = mockPluginManager + if (!(Holders.pluginManager instanceof DefaultGrailsPluginManager)) { + Holders.pluginManager = mockPluginManager } def entity = datastore.mappingContext.addPersistentEntity(domainClass) def enhancer = new TestGormEnhancer(datastore, transactionManager) enhancer.enhance entity - MockUtils.prepareForConstraintsTests(entity.javaClass) def dc = new DefaultGrailsDomainClass(entity.javaClass) datastore.mappingContext.addEntityValidator(entity, new GrailsDomainClassValidator(domainClass:dc)) instances.each { @@ -115,8 +112,8 @@ def disconnect() { session?.disconnect() - if (PluginManagerHolder.pluginManager?.is(mockPluginManager)) { - PluginManagerHolder.pluginManager = null + if (Holders.pluginManager?.is(mockPluginManager)) { + Holders.pluginManager = null } datastore.clearData()
diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SaveWithFailOnErrorDefaultSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SaveWithFailOnErrorDefaultSpec.groovy index 65ffcd3..e2e34ed 100644 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SaveWithFailOnErrorDefaultSpec.groovy +++ b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SaveWithFailOnErrorDefaultSpec.groovy
@@ -1,9 +1,9 @@ package org.grails.datastore.gorm import grails.gorm.tests.GormDatastoreSpec +import grails.validation.ConstrainedProperty import grails.validation.ValidationException -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import org.grails.core.support.GrailsDomainConfigurationUtil import org.grails.datastore.mapping.annotation.Entity import org.springframework.validation.Errors import org.springframework.validation.Validator
diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UniqueConstraintGroupSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UniqueConstraintGroupSpec.groovy index d2bfef1..e271809 100644 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UniqueConstraintGroupSpec.groovy +++ b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UniqueConstraintGroupSpec.groovy
@@ -2,9 +2,8 @@ import grails.gorm.tests.GormDatastoreSpec import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty +import grails.validation.ConstrainedProperty +import org.grails.core.support.GrailsDomainConfigurationUtil import org.springframework.validation.Errors import org.springframework.validation.Validator
diff --git a/grails-datastore-gorm/build.gradle b/grails-datastore-gorm/build.gradle index 29de9ef..472028b 100644 --- a/grails-datastore-gorm/build.gradle +++ b/grails-datastore-gorm/build.gradle
@@ -4,6 +4,9 @@ dependencies { compile project(":grails-datastore-core") + compile("org.grails:grails-validation:$grailsVersion") { + exclude group:'org.grails',module:'grails-core' + } compile("org.grails:grails-core:$grailsVersion") { exclude group:'aopalliance',module:'aopalliance' exclude group:'commons-logging',module:'commons-logging' @@ -18,6 +21,7 @@ exclude group:'oro',module:'oro' exclude group:'asm',module:'asm' exclude group:'cglib',module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'xalan',module:'serializer' exclude group:'org.springframework',module:'spring-aspects' exclude group:'org.springframework',module:'spring-beans'
diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java b/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java index 4c6d2d7..2dd93a5 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java
@@ -44,7 +44,7 @@ import org.springframework.util.Assert; /** - * Criteria builder implementation that operates against Spring datastore abstraction. + * Criteria builder implementation that operates against DataStore abstraction. * * @author Graeme Rocher * @since 1.0 @@ -244,7 +244,7 @@ * @return The result list */ public List list(Closure callable) { - initializeQuery(); + ensureQueryIsInitialized(); invokeClosureNode(callable); return query.list(); @@ -259,7 +259,7 @@ * @return A single result */ public Object get(Closure callable) { - initializeQuery(); + ensureQueryIsInitialized(); invokeClosureNode(callable); uniqueResult = true; @@ -273,7 +273,7 @@ * @return The result list */ public List listDistinct(Closure callable) { - initializeQuery(); + ensureQueryIsInitialized(); invokeClosureNode(callable); query.projections().distinct(); @@ -281,7 +281,7 @@ } public List list(Map paginateParams, Closure callable) { - initializeQuery(); + ensureQueryIsInitialized(); paginationEnabledList = true; orderEntries = new ArrayList<Query.Order>(); @@ -300,7 +300,7 @@ * @return The result count */ public Number count(Closure callable) { - initializeQuery(); + ensureQueryIsInitialized(); invokeClosureNode(callable); uniqueResult = true; query.projections().count(); @@ -316,9 +316,9 @@ public Object invokeMethod(String name, Object obj) { Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; + ensureQueryIsInitialized(); if (isCriteriaConstructionMethod(name, args)) { - initializeQuery(); uniqueResult = false; @@ -1085,9 +1085,13 @@ } } - private void initializeQuery() { - query = session.createQuery(targetClass); - queryMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(query.getClass()); + private void ensureQueryIsInitialized() { + if(query == null) { + query = session.createQuery(targetClass); + } + if(queryMetaClass == null) { + queryMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(query.getClass()); + } } private boolean isCriteriaConstructionMethod(String name, Object[] args) { @@ -1136,7 +1140,7 @@ } else { if (query == null) { - initializeQuery(); + ensureQueryIsInitialized(); } query.add(c); }
diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy index 60b6a66..11ca8d3 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy
@@ -29,7 +29,7 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target([ElementType.TYPE]) -@GroovyASTTransformationClass("org.codehaus.groovy.grails.compiler.gorm.DirtyCheckTransformation") +@GroovyASTTransformationClass("org.grails.compiler.gorm.DirtyCheckTransformation") public @interface DirtyCheck { } \ No newline at end of file
diff --git a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckTransformation.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckTransformation.groovy similarity index 96% rename from grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckTransformation.groovy rename to grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckTransformation.groovy index 67fdbfc..a4d3c44 100644 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckTransformation.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckTransformation.groovy
@@ -1,4 +1,4 @@ -package org.codehaus.groovy.grails.compiler.gorm +package org.grails.compiler.gorm import grails.gorm.dirty.checking.DirtyCheck import groovy.transform.CompileStatic
diff --git a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckingTransformer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy similarity index 97% rename from grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckingTransformer.groovy rename to grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy index 4faf94d..41d7fde 100644 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckingTransformer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy
@@ -1,6 +1,7 @@ -package org.codehaus.groovy.grails.compiler.gorm +package org.grails.compiler.gorm import grails.artefact.Artefact +import grails.util.GrailsClassUtils import groovy.transform.CompileStatic import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode @@ -28,15 +29,14 @@ import org.codehaus.groovy.ast.tools.GenericsUtils import org.codehaus.groovy.classgen.GeneratorContext import org.codehaus.groovy.control.SourceUnit -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsClassUtils -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil import org.codehaus.groovy.grails.compiler.injection.AstTransformer -import org.codehaus.groovy.grails.compiler.injection.GrailsArtefactClassInjector +import grails.compiler.ast.GrailsArtefactClassInjector +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.core.support.GrailsDomainConfigurationUtil -import static org.codehaus.groovy.grails.compiler.injection.GrailsASTUtils.* -import org.codehaus.groovy.grails.compiler.injection.GrailsDomainClassInjector -import org.codehaus.groovy.grails.io.support.GrailsResourceUtils +import static org.grails.compiler.injection.GrailsASTUtils.* +import grails.compiler.ast.GrailsDomainClassInjector +import org.grails.io.support.GrailsResourceUtils import org.codehaus.groovy.syntax.Token import org.codehaus.groovy.syntax.Types import org.grails.datastore.mapping.dirty.checking.DirtyCheckable
diff --git a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformer.java b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java similarity index 82% rename from grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformer.java rename to grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java index 75e6c42..d1a317c 100644 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformer.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java
@@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.codehaus.groovy.grails.compiler.gorm; +package org.grails.compiler.gorm; +import grails.compiler.ast.AstTransformer; import grails.persistence.Entity; import grails.persistence.PersistenceMethod; @@ -31,14 +32,12 @@ import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.metaclass.CreateDynamicMethod; -import org.codehaus.groovy.grails.compiler.injection.AbstractGrailsArtefactTransformer; -import org.codehaus.groovy.grails.compiler.injection.AstTransformer; -import org.codehaus.groovy.grails.compiler.injection.GrailsASTUtils; -import org.codehaus.groovy.grails.io.support.GrailsResourceUtils; +import org.grails.compiler.injection.AbstractGrailsArtefactTransformer; +import org.grails.compiler.injection.GrailsASTUtils; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.gorm.GormInstanceApi; import org.grails.datastore.gorm.GormStaticApi; +import org.grails.io.support.GrailsResourceUtils; /** * Transforms GORM entities making the GORM API available to Java. @@ -51,7 +50,8 @@ public static final String NEW_INSTANCE_METHOD = "newInstance"; - private static final Set<String> EXCLUDES = new HashSet<String>(Arrays.asList("create", "setTransactionManager")); + public static final String CREATE_METHOD_NAME = "create"; + private static final Set<String> EXCLUDES = new HashSet<String>(Arrays.asList(CREATE_METHOD_NAME, "setTransactionManager")); private static final Set<String> INCLUDES = new HashSet<String>(Arrays.asList("getAll", "getCount", "getValidationSkipMap", "getValidationErrorsMap", "getAsync")); private static final Set<String> TRANSFORMED_CLASSES = new HashSet<String>(); @@ -100,10 +100,10 @@ final BlockStatement methodBody = new BlockStatement(); methodBody.addStatement(new ExpressionStatement(new MethodCallExpression(new ClassExpression(classNode), NEW_INSTANCE_METHOD,ZERO_ARGS))); - MethodNode methodNode = classNode.getDeclaredMethod(CreateDynamicMethod.METHOD_NAME, ZERO_PARAMETERS); + MethodNode methodNode = classNode.getDeclaredMethod(CREATE_METHOD_NAME, ZERO_PARAMETERS); classNode = GrailsASTUtils.nonGeneric(classNode); if (methodNode == null) { - classNode.addMethod(new MethodNode(CreateDynamicMethod.METHOD_NAME, PUBLIC_STATIC_MODIFIER, classNode, ZERO_PARAMETERS,null, methodBody)); + classNode.addMethod(new MethodNode(CREATE_METHOD_NAME, PUBLIC_STATIC_MODIFIER, classNode, ZERO_PARAMETERS,null, methodBody)); } }
diff --git a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformer.java b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormValidationTransformer.java similarity index 81% rename from grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformer.java rename to grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormValidationTransformer.java index a125b91..72b5f41 100644 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformer.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormValidationTransformer.java
@@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.codehaus.groovy.grails.compiler.gorm; +package org.grails.compiler.gorm; import java.net.URL; import java.util.Arrays; +import grails.compiler.ast.AstTransformer; +import grails.core.GrailsDomainClassProperty; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.compiler.injection.ASTErrorsHelper; -import org.codehaus.groovy.grails.compiler.injection.ASTValidationErrorsHelper; -import org.codehaus.groovy.grails.compiler.injection.AbstractGrailsArtefactTransformer; -import org.codehaus.groovy.grails.compiler.injection.AstTransformer; -import org.codehaus.groovy.grails.io.support.GrailsResourceUtils; +import org.grails.compiler.injection.ASTErrorsHelper; +import org.grails.compiler.injection.ASTValidationErrorsHelper; +import org.grails.compiler.injection.AbstractGrailsArtefactTransformer; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.gorm.GormValidationApi; +import org.grails.io.support.GrailsResourceUtils; /** * Makes the validate methods statically available via an AST transformation. @@ -38,7 +38,7 @@ * @since 2.0 */ @AstTransformer -public class GormValidationTransformer extends AbstractGrailsArtefactTransformer{ +public class GormValidationTransformer extends AbstractGrailsArtefactTransformer { public static final String HAS_ERRORS_METHOD = "hasErrors"; private static final java.util.List<String> EXCLUDES = Arrays.asList( "setErrors", "getErrors", HAS_ERRORS_METHOD,
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy index ac679b8..05177ea 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy
@@ -14,13 +14,13 @@ */ package org.grails.datastore.gorm +import grails.util.GrailsMetaClassUtils import grails.util.GrailsNameUtils +import grails.validation.ConstrainedProperty import java.lang.reflect.Method import java.lang.reflect.Modifier -import org.codehaus.groovy.grails.commons.GrailsMetaClassUtils -import org.codehaus.groovy.grails.validation.ConstrainedProperty import org.codehaus.groovy.reflection.CachedMethod import org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod import org.codehaus.groovy.runtime.metaclass.MethodSelectionException
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy index 6efea51..1dcc2e2 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy
@@ -425,8 +425,8 @@ * * @return The list of all entities */ - List<D> findAll() { - list() + List<D> findAll(Map params = Collections.emptyMap()) { + list(params) } /** @@ -864,13 +864,12 @@ (Map<D, Boolean>)AbstractDatastore.getValidationSkipMap() } - // TODO: In the first version no support will exist for String-based queries List<D> executeQuery(String query) { - unsupported("executeQuery") + executeQuery(query, Collections.emptyMap(), Collections.emptyMap()) } List<D> executeQuery(String query, Map args) { - unsupported("executeQuery") + executeQuery(query, args, args) } List<D> executeQuery(String query, Map params, Map args) { @@ -878,7 +877,11 @@ } List<D> executeQuery(String query, Collection params) { - unsupported("executeQuery") + executeQuery(query, params, Collections.emptyMap()) + } + + List<D> executeQuery(String query, Object...params) { + executeQuery(query, params.toList(), Collections.emptyMap()) } List<D> executeQuery(String query, Collection params, Map args) { @@ -886,11 +889,11 @@ } Integer executeUpdate(String query) { - unsupported("executeUpdate") + executeUpdate(query, Collections.emptyMap(), Collections.emptyMap()) } Integer executeUpdate(String query, Map args) { - unsupported("executeUpdate") + executeUpdate(query, args, args) } Integer executeUpdate(String query, Map params, Map args) { @@ -898,7 +901,11 @@ } Integer executeUpdate(String query, Collection params) { - unsupported("executeUpdate") + executeUpdate(query, params, Collections.emptyMap()) + } + + Integer executeUpdate(String query, Object...params) { + executeUpdate(query, params.toList(), Collections.emptyMap()) } Integer executeUpdate(String query, Collection params, Map args) { @@ -906,11 +913,11 @@ } D find(String query) { - unsupported("find") + find(query, Collections.emptyMap()) } D find(String query, Map args) { - unsupported("find") + find(query, args, args) } D find(String query, Map params, Map args) { @@ -918,7 +925,11 @@ } D find(String query, Collection params) { - unsupported("find") + find(query, params, Collections.emptyMap()) + } + + D find(String query, Object[] params) { + find(query, params.toList(), Collections.emptyMap()) } D find(String query, Collection params, Map args) { @@ -926,11 +937,11 @@ } List<D> findAll(String query) { - unsupported("findAll") + findAll(query, Collections.emptyMap(), Collections.emptyMap()) } - List<D> findAll(String query, Map args) { - unsupported("findAll") + List<D> findAll(String query, Map params) { + findAll(query, params, params) } List<D> findAll(String query, Map params, Map args) { @@ -938,7 +949,11 @@ } List<D> findAll(String query, Collection params) { - unsupported("find") + findAll(query, params, Collections.emptyMap()) + } + + List<D> findAll(String query, Object[] params) { + findAll(query, params.toList(), Collections.emptyMap()) } List<D> findAll(String query, Collection params, Map args) {
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidationApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidationApi.groovy index 6f2f340..d3666ed 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidationApi.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidationApi.groovy
@@ -14,7 +14,7 @@ */ package org.grails.datastore.gorm -import org.codehaus.groovy.grails.validation.CascadingValidator +import grails.validation.CascadingValidator import org.grails.datastore.gorm.support.BeforeValidateHelper import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.engine.event.ValidationEvent @@ -145,17 +145,6 @@ doValidate instance, (Map)null, (List)null } - /** - * Validates an instance. Note: This signature is purely here for compatibility the - * evict parameter does nothing and the method should be regarded as deprecated - * - * @param instance The instance to validate - * @return True if the instance is valid - */ - @Deprecated - boolean validate(D instance, boolean evict) { - doValidate instance, (Map)null, (List)null - } /** * Obtains the errors for an instance
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethods.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethods.groovy new file mode 100644 index 0000000..50c8393 --- /dev/null +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethods.groovy
@@ -0,0 +1,27 @@ +/* + * Copyright 2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.grails.datastore.gorm + +import groovy.transform.CompileStatic +/** + * + * @author Jeff Brown + * @since 4.0 + */ +@CompileStatic +trait StaticQueryMethods<D> { + // methods removed for now... +}
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitInjector.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitInjector.groovy new file mode 100644 index 0000000..3f49c88 --- /dev/null +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitInjector.groovy
@@ -0,0 +1,46 @@ +/* + * Copyright 2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.grails.datastore.gorm + +import grails.compiler.traits.TraitInjector +import groovy.transform.CompileStatic + +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.io.support.GrailsResourceUtils + +/** + * + * @author Jeff Brown + * @since 4.0 + * + */ +@CompileStatic +class StaticQueryMethodsTraitInjector implements TraitInjector { + + Class getTrait() { + StaticQueryMethods + } + + @Override + boolean shouldInject(URL url) { + GrailsResourceUtils.isDomainClass(url) + } + + @Override + String[] getArtefactTypes() { + [DomainClassArtefactHandler.TYPE] as String[] + } +}
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy index 701ed91..c5e074d 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy
@@ -15,8 +15,8 @@ package org.grails.datastore.gorm.async import grails.async.DelegateAsync -import org.grails.async.decorator.PromiseDecorator -import org.grails.async.decorator.PromiseDecoratorProvider +import grails.async.decorator.PromiseDecorator +import grails.async.decorator.PromiseDecoratorProvider import org.grails.datastore.gorm.query.GormOperations /** @@ -25,7 +25,7 @@ * @author Graeme Rocher * @since 2.3 */ -class AsyncQuery<E> implements PromiseDecoratorProvider{ +class AsyncQuery<E> implements PromiseDecoratorProvider { @DelegateAsync GormOperations<E> gormOperations
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy index 1e02cbb..c990a64 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy
@@ -16,9 +16,9 @@ import grails.async.Promise import grails.async.Promises +import grails.async.decorator.PromiseDecorator +import grails.async.decorator.PromiseDecoratorProvider import groovy.transform.CompileStatic -import org.grails.async.decorator.PromiseDecorator -import org.grails.async.decorator.PromiseDecoratorProvider import org.grails.datastore.gorm.GormStaticApi /**
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bean/factory/AbstractMappingContextFactoryBean.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bean/factory/AbstractMappingContextFactoryBean.groovy index dcfc02f..099c4fa 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bean/factory/AbstractMappingContextFactoryBean.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bean/factory/AbstractMappingContextFactoryBean.groovy
@@ -14,11 +14,11 @@ */ package org.grails.datastore.gorm.bean.factory +import grails.core.GrailsApplication +import grails.core.GrailsDomainClass +import grails.core.support.GrailsApplicationAware import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware import org.grails.datastore.gorm.proxy.GroovyProxyFactory import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy index 9a81a65..429349a 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy
@@ -1,14 +1,17 @@ package org.grails.datastore.gorm.bootstrap +import grails.config.Config +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.compiler.gorm.GormTransformer -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator +import org.grails.compiler.gorm.GormTransformer +import org.grails.config.PropertySourcesConfig +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.validation.GrailsDomainClassValidator import org.springframework.beans.factory.config.MethodInvokingFactoryBean import org.springframework.beans.factory.support.BeanDefinitionRegistry import org.springframework.context.ResourceLoaderAware +import org.springframework.core.env.MutablePropertySources import org.springframework.core.io.Resource import org.springframework.core.io.ResourceLoader import org.springframework.core.io.support.PathMatchingResourcePatternResolver @@ -29,8 +32,9 @@ ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver() Collection<Class> persistentClasses = [] Collection<String> packages = [] - Properties configuration = new Properties() - ConfigObject configurationObject = new ConfigObject() + Map configuration = new LinkedHashMap() + Config configurationObject = new PropertySourcesConfig() + boolean registerApplicationIfNotPresent = true protected ClassLoader classLoader = Thread.currentThread().contextClassLoader @@ -53,12 +57,18 @@ this(persistentClasses.toList()) } - AbstractDatastoreInitializer(Properties configuration, Collection<Class> persistentClasses) { + AbstractDatastoreInitializer(Map configuration, Collection<Class> persistentClasses) { this.configuration = configuration this.persistentClasses = persistentClasses + if(configuration instanceof Config) { + this.configurationObject = (Config)configuration + } + else { + this.configurationObject.merge((Map<String,Object>)configuration) + } } - AbstractDatastoreInitializer(Properties configuration, Class... persistentClasses) { + AbstractDatastoreInitializer(Map configuration, Class... persistentClasses) { this(configuration, persistentClasses.toList()) } @@ -113,7 +123,7 @@ */ @CompileStatic void configureForBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) { - this.configurationObject = new ConfigSlurper().parse(configuration) + scanForPersistentClasses() ExpandoMetaClass.enableGlobally() @@ -135,7 +145,7 @@ context.'annotation-config'() - if(!registry.containsBeanDefinition(GrailsApplication.APPLICATION_ID)) { + if(!registry.containsBeanDefinition(GrailsApplication.APPLICATION_ID) && registerApplicationIfNotPresent) { grailsApplication(DefaultGrailsApplication, persistentClasses as Class[], Thread.currentThread().contextClassLoader) { bean -> bean.initMethod = 'initialise' }
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassMappingContext.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassMappingContext.java index febd49a..2411338 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassMappingContext.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassMappingContext.java
@@ -15,10 +15,10 @@ package org.grails.datastore.gorm.config; -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.commons.GrailsClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; +import grails.core.GrailsApplication; +import grails.core.GrailsClass; +import grails.core.GrailsDomainClass; +import org.grails.core.artefact.DomainClassArtefactHandler; import org.grails.datastore.mapping.model.AbstractMappingContext; import org.grails.datastore.mapping.model.MappingConfigurationStrategy; import org.grails.datastore.mapping.model.MappingFactory;
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentEntity.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentEntity.java index ca36bf8..de144cc 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentEntity.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentEntity.java
@@ -20,8 +20,8 @@ import java.util.List; import java.util.Map; -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClass; +import grails.core.GrailsDomainClassProperty; import org.grails.datastore.mapping.model.ClassMapping; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; @@ -275,9 +275,9 @@ association.setReferencedPropertyName(referencedPropertyName); } else { - GrailsDomainClassProperty otherSide = grailsDomainClassProperty.getOtherSide(); - if(otherSide != null) { - association.setReferencedPropertyName(otherSide.getName()); + GrailsDomainClassProperty otherSide = grailsDomainClassProperty.getOtherSide(); + if(otherSide != null) { + association.setReferencedPropertyName(otherSide.getName()); } } }
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentProperty.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentProperty.java index fe9d65e..4f73e74 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentProperty.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentProperty.java
@@ -15,7 +15,7 @@ package org.grails.datastore.gorm.config; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; +import grails.core.GrailsDomainClassProperty; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.PropertyMapping;
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java index 36da346..882dcc9 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java
@@ -27,14 +27,7 @@ } protected Object invokeQuery(Query q) { - q.max(1); - - List<?> results = q.list(); - if (results.isEmpty()) { - return null; - } - - return results.get(0); + return q.singleResult(); } public boolean firstExpressionIsRequiredBoolean() {
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java index 3d48e5c..e8efa09 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java
@@ -15,15 +15,12 @@ package org.grails.datastore.gorm.finders; import grails.gorm.DetachedCriteria; +import grails.util.GrailsClassUtils; import groovy.lang.Closure; import groovy.lang.MissingMethodException; import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,6 +57,11 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public abstract class DynamicFinder extends AbstractFinder implements QueryBuildingFinder { + + public static final String ARGUMENT_FETCH_SIZE = "fetchSize"; + public static final String ARGUMENT_TIMEOUT = "timeout"; + public static final String ARGUMENT_READ_ONLY = "readOnly"; + public static final String ARGUMENT_FLUSH_MODE = "flushMode"; public static final String ARGUMENT_MAX = "max"; public static final String ARGUMENT_OFFSET = "offset"; public static final String ARGUMENT_ORDER = "order"; @@ -71,6 +73,8 @@ public static final String ARGUMENT_CACHE = "cache"; public static final String ARGUMENT_LOCK = "lock"; + + protected Pattern pattern; private Pattern[] operatorPatterns; private String[] operators; @@ -384,8 +388,13 @@ } } - final String sort = (String)argMap.get(ARGUMENT_SORT); - final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; + if(argMap.containsKey(ARGUMENT_CACHE)) { + q.cache(GrailsClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); + } + if(argMap.containsKey(ARGUMENT_LOCK)) { + q.lock(GrailsClassUtils.getBooleanFromMap(ARGUMENT_LOCK, argMap)); + } + final int max = maxParam == null ? -1 : maxParam; final int offset = offsetParam == null ? -1 : offsetParam; if (max > -1) { @@ -394,19 +403,52 @@ if (offset > -1) { q.offset(offset); } - if (sort != null) { - if (ORDER_DESC.equalsIgnoreCase(order)) { - q.order(Query.Order.desc(sort)); + Object sortObject = argMap.get(ARGUMENT_SORT); + boolean ignoreCase = !argMap.containsKey(ARGUMENT_IGNORE_CASE) || GrailsClassUtils.getBooleanFromMap(ARGUMENT_IGNORE_CASE, argMap); + + if (sortObject != null) { + if(sortObject instanceof CharSequence) { + final String sort = sortObject.toString(); + final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; + addSimpleSort(q, sort, order, ignoreCase); } - else { - q.order(Query.Order.asc(sort)); + else if(sortObject instanceof Map) { + Map sortMap = (Map)sortObject; + applySortForMap(q, sortMap, ignoreCase); + } } + if (q instanceof QueryArgumentsAware) { ((QueryArgumentsAware)q).setArguments(argMap); } } + + private static void addSimpleSort(Query q, String sort, String order, boolean ignoreCase) { + Query.Order o; + if (ORDER_DESC.equalsIgnoreCase(order)) { + o = Query.Order.desc(sort); + } + else { + o = Query.Order.asc(sort); + } + + if(ignoreCase) o = o.ignoreCase(); + + q.order(o); + } + + public static void applySortForMap(Query q, Map sortMap, boolean ignoreCase) { + for (Object key : sortMap.keySet()) { + Object value = sortMap.get(key); + String sort = key.toString(); + String order = value != null ? value.toString() : ORDER_ASC; + + addSimpleSort(q, sort, order, ignoreCase); + } + } + /** * Retrieves the fetch mode for the specified instance; otherwise returns the default FetchMode. * @@ -426,6 +468,7 @@ protected void configureQueryWithArguments(Class clazz, Query query, Object[] arguments) { if (arguments.length == 0 || !(arguments[0] instanceof Map)) { + populateArgumentsForCriteria(clazz, query, Collections.emptyMap()); return; }
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java index 1c0cc53..5318054 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java
@@ -16,10 +16,7 @@ import groovy.lang.Range; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; @@ -184,9 +181,12 @@ @Override public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof Collection, + Assert.isTrue(arguments.length > 0, "Only a collection of elements is supported in an 'in' query"); + Object arg = arguments[0]; + Assert.isTrue( (arg instanceof Collection) || arg == null, "Only a collection of elements is supported in an 'in' query"); + super.setArguments(arguments); } @@ -204,12 +204,18 @@ if (prop != null) { Class<?> type = prop.getType(); Collection<?> collection = (Collection<?>) arguments[0]; - List<Object> converted = new ArrayList<Object>(collection.size()); - for (Object o : collection) { - if (o != null && !type.isAssignableFrom(o.getClass())) { - o = conversionService.convert(o, type); + List<Object> converted; + if(collection == null) { + converted = Collections.emptyList(); + } + else { + converted = new ArrayList<Object>(collection.size()); + for (Object o : collection) { + if (o != null && !type.isAssignableFrom(o.getClass())) { + o = conversionService.convert(o, type); + } + converted.add(o); } - converted.add(o); } arguments[0] = converted; }
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java index 8bcc3e7..3f3ea46 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java
@@ -14,8 +14,10 @@ */ package org.grails.datastore.gorm.query.transform; +import grails.core.GrailsDomainClassProperty; import grails.gorm.DetachedCriteria; import grails.persistence.Entity; +import grails.util.GrailsClassUtils; import grails.util.GrailsNameUtils; import java.io.File; @@ -66,9 +68,7 @@ import org.codehaus.groovy.ast.stmt.*; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.messages.LocatedMessage; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.compiler.injection.GrailsASTUtils; +import org.grails.compiler.injection.GrailsASTUtils; import org.codehaus.groovy.syntax.Token; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion;
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java index 6076d71..bd06382 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java
@@ -16,9 +16,9 @@ import javax.persistence.FlushModeType; +import grails.persistence.support.PersistenceContextInterceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.Session;
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java index 156bcf5..a2fe37e 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java
@@ -51,13 +51,7 @@ } private static EventTriggerCaller resolveMetaMethodCaller(String eventMethodName, MetaClass metaClass) { - MetaMethod metaMethod = null; - for(MetaMethod mm : metaClass.getMetaMethods()) { - if(eventMethodName.equals(mm.getName())) { - metaMethod = mm; - break; - } - } + MetaMethod metaMethod = metaClass.getMetaMethod(eventMethodName, EMPTY_ARRAY); if (metaMethod != null) { return new MetaMethodCaller(metaMethod); }
diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java index 735ce82..a0474ff 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java
@@ -21,7 +21,7 @@ * Extends the default Spring Validator interface and provides an additional method that specifies whether * validation should cascade into associations. */ -public interface CascadingValidator extends Validator, org.codehaus.groovy.grails.validation.CascadingValidator { +public interface CascadingValidator extends Validator, grails.validation.CascadingValidator { /** * An extended version of the validate(errors,obj) method that takes an additional argument specifying whether
diff --git a/grails-datastore-gorm/src/main/resources/META-INF/grails.factories b/grails-datastore-gorm/src/main/resources/META-INF/grails.factories new file mode 100644 index 0000000..a27221e --- /dev/null +++ b/grails-datastore-gorm/src/main/resources/META-INF/grails.factories
@@ -0,0 +1 @@ +grails.compiler.traits.TraitInjector=org.grails.datastore.gorm.StaticQueryMethodsTraitInjector
diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitSpec.groovy new file mode 100644 index 0000000..6949eaf --- /dev/null +++ b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/StaticQueryMethodsTraitSpec.groovy
@@ -0,0 +1,39 @@ +package org.grails.datastore.gorm + +import grails.artefact.Artefact +import grails.persistence.Entity +import spock.lang.Specification + +class StaticQueryMethodsTraitSpec extends Specification { + + void "test that a class marked with @Artefact('Domain') is enhanced with StaticQueryMethods"() { + expect: + StaticQueryMethods.isAssignableFrom QueryMethodArtefactDomain + } + + void "test that a class marked with @Entity is enhanced with StaticQueryMethods"() { + expect: + StaticQueryMethods.isAssignableFrom QueryMethodEntityDomain + } + + void 'test that generic return values are respected'() { + when: + def method = QueryMethodArtefactDomain.methods.find { method -> + def rt = method.getParameterTypes() + rt && rt[0] == Closure && method.name == 'find' + } + + then: + method.returnType == QueryMethodArtefactDomain + } +} + +@Artefact('Domain') +class QueryMethodArtefactDomain { + String name +} + +@Entity +class QueryMethodEntityDomain { + String name +}
diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProviderSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProviderSpec.groovy index 3c5fe52..1fbc7bb 100644 --- a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProviderSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProviderSpec.groovy
@@ -2,7 +2,7 @@ import grails.spring.BeanBuilder -import org.codehaus.groovy.grails.commons.InstanceFactoryBean +import org.grails.spring.beans.factory.InstanceFactoryBean import spock.lang.Specification
diff --git a/grails-datastore-jcr/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-jcr/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index c7e431b..0000000 --- a/grails-datastore-jcr/src/test/groovy/grails/persistence/Entity.java +++ /dev/null
@@ -1,15 +0,0 @@ -package grails.persistence; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -public @interface Entity { -} \ No newline at end of file
diff --git a/grails-datastore-jpa/build.gradle b/grails-datastore-jpa/build.gradle index 61606b0..5e68a90 100644 --- a/grails-datastore-jpa/build.gradle +++ b/grails-datastore-jpa/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" configurations { grails
diff --git a/grails-datastore-rest-client/build.gradle b/grails-datastore-rest-client/build.gradle index 3b483f4..5376c11 100644 --- a/grails-datastore-rest-client/build.gradle +++ b/grails-datastore-rest-client/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.2.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies { compile 'javax.servlet:javax.servlet-api:3.0.1' // compile("org.grails:grails-plugin-codecs:$grailsVersion") { @@ -17,6 +17,8 @@ // exclude group:'org.grails', module:'grails-plugin-controllers' // exclude group:'org.grails', module:'grails-web' // } + + compile("org.grails:grails-async:$grailsVersion") compile("org.grails:grails-core:$grailsVersion") { exclude group:'commons-collections', module:'commons-collections' exclude group:'com.googlecode.concurrentlinkedhashmap', module:'concurrentlinkedhashmap-lru' @@ -33,6 +35,7 @@ exclude group:'asm', module:'asm' exclude group:'aopalliance', module:'aopalliance' exclude group:'cglib', module:'cglib' + exclude group:'cglib', module:'cglib-nodep' exclude group:'commons-validator', module:'commons-validator' exclude group:'org.hibernate.javax.persistence', module:'hibernate-jpa-2.0-api' }
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RequestCustomizer.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RequestCustomizer.groovy index 4b7dac4..f4b9541 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RequestCustomizer.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RequestCustomizer.groovy
@@ -21,7 +21,7 @@ import groovy.util.slurpersupport.GPathResult import groovy.xml.StreamingMarkupBuilder import org.apache.commons.codec.binary.Base64 -import org.codehaus.groovy.grails.web.json.JSONElement +import org.grails.web.json.JSONElement import org.springframework.core.io.FileSystemResource import org.springframework.core.io.InputStreamResource import org.springframework.core.io.UrlResource @@ -31,7 +31,7 @@ import org.springframework.util.LinkedMultiValueMap import org.springframework.util.MultiValueMap -import static org.codehaus.groovy.grails.web.servlet.HttpHeaders.* +import static grails.web.http.HttpHeaders.* /** * Core of the DSL for building REST requests @@ -171,7 +171,7 @@ * @return The customizer */ RequestCustomizer header(String name, String value) { - headers[name] = value + headers.add name, value return this }
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestBuilder.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestBuilder.groovy index 05101cf..756aca2 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestBuilder.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestBuilder.groovy
@@ -14,31 +14,32 @@ */ package grails.plugins.rest.client +import static org.springframework.http.HttpMethod.* + +import java.net.Proxy + import grails.converters.JSON import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationHolder -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationInitializer -import org.codehaus.groovy.grails.web.converters.configuration.DefaultConverterConfiguration + import org.grails.datastore.gorm.rest.client.json.GsonHttpMessageConverter import org.grails.datastore.gorm.rest.client.json.JsonHttpMessageConverter import org.grails.datastore.gorm.rest.client.utils.GrailsConverterHttpMessageConverter import org.grails.datastore.gorm.rest.client.utils.NullSafeStringHttpMessageConverter import org.grails.datastore.gorm.rest.client.utils.WritableHttpMessageConverter import org.grails.datastore.gorm.rest.client.xml.GPathXmlHttpMessageConverter +import org.grails.web.converters.configuration.ConvertersConfigurationHolder +import org.grails.web.converters.configuration.ConvertersConfigurationInitializer +import org.grails.web.converters.configuration.DefaultConverterConfiguration import org.springframework.http.HttpMethod import org.springframework.http.ResponseEntity import org.springframework.http.client.SimpleClientHttpRequestFactory import org.springframework.http.converter.HttpMessageConverter import org.springframework.http.converter.StringHttpMessageConverter import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter -import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter import org.springframework.util.ClassUtils import org.springframework.web.client.HttpStatusCodeException import org.springframework.web.client.RestTemplate -import static org.springframework.http.HttpMethod.* - /** * Main API entry to the synchronous version of the REST low-level client API * @@ -54,7 +55,7 @@ if(ConvertersConfigurationHolder.getConverterConfiguration(JSON) instanceof DefaultConverterConfiguration) { // init manually - new ConvertersConfigurationInitializer().initialize(new DefaultGrailsApplication()) + new ConvertersConfigurationInitializer().initialize() } Proxy proxyFromSystemProperties = getProxyForSystemProperties() @@ -288,10 +289,6 @@ if(mappingJackson2HttpMessageConverter) { messageConverters.remove(mappingJackson2HttpMessageConverter) } - final mappingJacksonHttpMessageConverter = messageConverters.find { HttpMessageConverter httpMessageConverter -> httpMessageConverter instanceof MappingJacksonHttpMessageConverter } - if(mappingJacksonHttpMessageConverter) { - messageConverters.remove(mappingJacksonHttpMessageConverter) - } if(ClassUtils.isPresent("com.google.gson.Gson", getClass().getClassLoader())) { messageConverters.add(new GsonHttpMessageConverter()) }
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestResponse.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestResponse.groovy index d21b4cb..5d3f5db 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestResponse.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestResponse.groovy
@@ -20,7 +20,7 @@ import groovy.transform.TypeCheckingMode import groovy.util.slurpersupport.GPathResult import groovy.xml.StreamingMarkupBuilder -import org.codehaus.groovy.grails.web.json.JSONElement +import org.grails.web.json.JSONElement import org.springframework.http.ResponseEntity import org.springframework.web.client.HttpStatusCodeException
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncJsonResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncJsonResourcesClient.groovy index 01ed517..012adc3 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncJsonResourcesClient.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncJsonResourcesClient.groovy
@@ -19,7 +19,7 @@ import grails.plugins.rest.client.async.AsyncRestBuilder import grails.plugins.rest.client.templated.JsonResourcesClient import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.json.JSONElement +import org.grails.web.json.JSONElement import org.springframework.http.MediaType /**
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/JsonResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/JsonResourcesClient.groovy index 7164e69..bf02c34 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/JsonResourcesClient.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/JsonResourcesClient.groovy
@@ -18,9 +18,9 @@ import grails.plugins.rest.client.RestBuilder import grails.plugins.rest.client.RestResponse import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.converters.ConverterUtil -import org.codehaus.groovy.grails.web.json.JSONElement import org.codehaus.groovy.runtime.typehandling.GroovyCastException +import org.grails.web.converters.ConverterUtil +import org.grails.web.json.JSONElement /** * A simple client for interacting with a REST web service exposed by a Grails application
diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/XmlResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/XmlResourcesClient.groovy index f6937bd..22e7c80 100644 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/XmlResourcesClient.groovy +++ b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/XmlResourcesClient.groovy
@@ -18,8 +18,8 @@ import grails.plugins.rest.client.RestBuilder import groovy.transform.CompileStatic import groovy.util.slurpersupport.GPathResult -import org.codehaus.groovy.grails.web.converters.ConverterUtil import org.codehaus.groovy.runtime.typehandling.GroovyCastException +import org.grails.web.converters.ConverterUtil /** *
diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/JsonHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/JsonHttpMessageConverter.groovy index ac9d319..94d3a7c 100644 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/JsonHttpMessageConverter.groovy +++ b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/JsonHttpMessageConverter.groovy
@@ -16,7 +16,7 @@ import grails.converters.JSON import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.json.JSONElement +import org.grails.web.json.JSONElement import org.springframework.http.HttpInputMessage import org.springframework.http.HttpOutputMessage import org.springframework.http.MediaType
diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/GrailsConverterHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/GrailsConverterHttpMessageConverter.groovy index ce52b15..cad6a45 100644 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/GrailsConverterHttpMessageConverter.groovy +++ b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/GrailsConverterHttpMessageConverter.groovy
@@ -15,7 +15,7 @@ package org.grails.datastore.gorm.rest.client.utils import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.converters.Converter +import org.grails.web.converters.Converter import org.springframework.http.HttpInputMessage import org.springframework.http.HttpOutputMessage import org.springframework.http.MediaType
diff --git a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/AsyncRestBuilderSpec.groovy b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/AsyncRestBuilderSpec.groovy index e086486..950121f 100644 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/AsyncRestBuilderSpec.groovy +++ b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/AsyncRestBuilderSpec.groovy
@@ -4,12 +4,10 @@ import grails.converters.JSON import grails.plugins.rest.client.async.AsyncRestBuilder import grails.web.JSONBuilder +import grails.web.http.HttpHeaders import groovy.util.slurpersupport.GPathResult -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationHolder -import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationInitializer -import org.codehaus.groovy.grails.web.json.JSONArray -import org.codehaus.groovy.grails.web.json.JSONObject +import org.grails.web.json.JSONArray +import org.grails.web.json.JSONObject import spock.lang.Issue import spock.lang.Specification @@ -21,7 +19,6 @@ import org.springframework.http.HttpMethod import static org.springframework.test.web.client.match.MockRestRequestMatchers.header -import org.codehaus.groovy.grails.web.servlet.HttpHeaders import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess import org.springframework.http.MediaType
diff --git a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/RestBuilderSpec.groovy b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/RestBuilderSpec.groovy index 7651cd4..a7fac30 100644 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/RestBuilderSpec.groovy +++ b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/RestBuilderSpec.groovy
@@ -2,10 +2,10 @@ import grails.converters.JSON import grails.web.JSONBuilder +import grails.web.http.HttpHeaders import groovy.util.slurpersupport.GPathResult -import org.codehaus.groovy.grails.web.json.JSONArray -import org.codehaus.groovy.grails.web.json.JSONObject -import org.codehaus.groovy.grails.web.servlet.HttpHeaders +import org.grails.web.json.JSONArray +import org.grails.web.json.JSONObject import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus import org.springframework.http.MediaType
diff --git a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/templated/JsonResourcesClientSpec.groovy b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/templated/JsonResourcesClientSpec.groovy index 622008a..a574a94 100644 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/templated/JsonResourcesClientSpec.groovy +++ b/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/templated/JsonResourcesClientSpec.groovy
@@ -1,7 +1,7 @@ package grails.plugins.rest.client.templated import grails.plugins.rest.client.RestBuilder -import org.codehaus.groovy.grails.web.json.JSONObject +import org.grails.web.json.JSONObject import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus import org.springframework.http.MediaType @@ -87,6 +87,7 @@ } + @spock.lang.Ignore void "Test that the post method correctly sends JSON to the appropriate URL"() { setup: RestBuilder restBuilder = new RestBuilder()
diff --git a/grails-datastore-riak/build.gradle b/grails-datastore-riak/build.gradle index 7b4bda7..d0c097e 100644 --- a/grails-datastore-riak/build.gradle +++ b/grails-datastore-riak/build.gradle
@@ -1,4 +1,4 @@ -version = "1.0.0.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies { compile project(":grails-datastore-core"),
diff --git a/grails-datastore-simpledb/build.gradle b/grails-datastore-simpledb/build.gradle index 262f04f..22d3b64 100644 --- a/grails-datastore-simpledb/build.gradle +++ b/grails-datastore-simpledb/build.gradle
@@ -1,4 +1,4 @@ -version = "0.6.BUILD-SNAPSHOT" +//version = "4.0.0.BUILD-SNAPSHOT" dependencies { compile project(":grails-datastore-core")
diff --git a/grails-plugins/hibernate/build.gradle b/grails-plugins/hibernate/build.gradle new file mode 100644 index 0000000..6518038 --- /dev/null +++ b/grails-plugins/hibernate/build.gradle
@@ -0,0 +1,44 @@ + +group = "org.grails.plugins" +version = "4.3.5.5.BUILD-SNAPSHOT" + +apply from:'https://raw.githubusercontent.com/grails/grails-boot/master/gradle/maven-central-build.gradle' + +configurations { + provided +} + +dependencies { + + + provided("org.grails:grails-core:$grailsVersion") + compile 'org.codehaus.groovy:groovy:2.3.7' + + compile project(":grails-datastore-gorm-hibernate4"), { + exclude group:'org.springframework', module:'spring-context' + exclude group:'org.springframework', module:'spring-core' + exclude group:'org.springframework', module:'spring-beans' + exclude group:'org.springframework', module:'spring-tx' + exclude group:'org.grails', module:'grails-bootstrap' + exclude group:'org.codehaus.groovy', module:'groovy-all' + exclude group:'org.grails', module:'grails-core' + exclude group:'org.grails', module:'grails-async' + exclude group:'javax.transaction', module:'jta' + } +} + +sourceSets { + main { + compileClasspath += configurations.provided + } + javadoc { + classpath = configurations.compile + configurations.provided + } +} + +def installer = install.repositories.mavenInstaller +def deployer = uploadArchives.repositories.mavenDeployer + +[installer, deployer]*.pom*.whenConfigured { pom -> + pom.artifactId = 'hibernate' +} \ No newline at end of file
diff --git a/grails-plugins/hibernate/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-plugins/hibernate/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy new file mode 100644 index 0000000..8d52e44 --- /dev/null +++ b/grails-plugins/hibernate/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy
@@ -0,0 +1,76 @@ +package grails.plugin.hibernate + +import grails.config.Config +import grails.core.GrailsApplication +import grails.core.GrailsClass +import grails.core.GrailsDomainClassProperty +import grails.core.support.GrailsApplicationAware +import grails.orm.bootstrap.HibernateDatastoreSpringInitializer +import grails.plugins.Plugin +import groovy.transform.CompileStatic +import org.grails.core.artefact.DomainClassArtefactHandler +import org.springframework.beans.factory.support.BeanDefinitionRegistry + +/** + * Plugin that integrates Hibernate into a Grails application + * + * @author Graeme Rocher + * @since 3.0 + */ +@CompileStatic +class HibernateGrailsPlugin extends Plugin { + + + def version = '4.3.5.5-SNAPSHOT' + def grailsVersion = '2.3.5 > *' + def author = 'Burt Beckwith' + def title = 'Hibernate 4 for Grails' + def description = 'Provides integration between Grails and Hibernate 4 through GORM' + def documentation = 'http://grails.org/plugin/hibernate4' + + def observe = ['domainClass'] + def loadAfter = ['controllers', 'domainClass'] + def watchedResources = ['file:./grails-app/conf/hibernate/**.xml'] + def pluginExcludes = ['src/templates/**'] + + def license = 'APACHE' + def organization = [name: 'Pivotal', url: 'http://pivotal.io'] + def issueManagement = [system: 'JIRA', url: 'http://jira.grails.org/browse/GPHIB'] + def scm = [url: 'https://github.com/grails-plugins/grails-hibernate4-plugin'] + + + Closure doWithSpring() {{-> + GrailsApplication grailsApplication = grailsApplication + Set<String> datasourceNames = [] + + Config config = grailsApplication.config + Map dataSources = config.getProperty('dataSources', Map, [:]) + + if(dataSources) { + for (name in config.keySet()) { + if(name == 'dataSource') { + datasourceNames << GrailsDomainClassProperty.DEFAULT_DATA_SOURCE + } + else { + datasourceNames << name + } + } + } + else { + Map dataSource = config.getProperty('dataSource', Map, [:]) + if(dataSource) { + datasourceNames << GrailsDomainClassProperty.DEFAULT_DATA_SOURCE + } + } + + + def springInitializer = new HibernateDatastoreSpringInitializer(config, grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE).collect() { GrailsClass cls -> cls.clazz }) + springInitializer.registerApplicationIfNotPresent = false + springInitializer.dataSources = datasourceNames + def beans = springInitializer.getBeanDefinitions((BeanDefinitionRegistry)applicationContext) + + beans.delegate = delegate + beans.call() + }} + +}
diff --git a/grails-plugins/mongodb/.classpath b/grails-plugins/mongodb/.classpath deleted file mode 100644 index 27107c2..0000000 --- a/grails-plugins/mongodb/.classpath +++ /dev/null
@@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="grails-app/conf"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="src" path=".link_to_grails_plugins/release-2.2.0/src/groovy"> - <attributes> - <attribute name="org.grails.ide.eclipse.core.SOURCE_FOLDER" value="true"/> - </attributes> - </classpathentry> - <classpathentry kind="src" path=".link_to_grails_plugins/release-2.2.0/src/java"> - <attributes> - <attribute name="org.grails.ide.eclipse.core.SOURCE_FOLDER" value="true"/> - </attributes> - </classpathentry> - <classpathentry kind="src" path=".link_to_grails_plugins/rest-client-builder-1.0.3/src/groovy"> - <attributes> - <attribute name="org.grails.ide.eclipse.core.SOURCE_FOLDER" value="true"/> - </attributes> - </classpathentry> - <classpathentry kind="con" path="org.grails.ide.eclipse.core.CLASSPATH_CONTAINER"/> - <classpathentry kind="output" path="target/eclipseclasses"/> -</classpath>
diff --git a/grails-plugins/mongodb/.project b/grails-plugins/mongodb/.project deleted file mode 100644 index c173311..0000000 --- a/grails-plugins/mongodb/.project +++ /dev/null
@@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>mongodb</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.grails.ide.eclipse.core.nature</nature> - <nature>org.eclipse.jdt.groovy.core.groovyNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> - <linkedResources> - <link> - <name>.link_to_grails_plugins</name> - <type>2</type> - <location>/home/burt/workspace.nosql/grails-data-mapping/grails-plugins/mongodb/target/plugins</location> - </link> - </linkedResources> -</projectDescription>
diff --git a/grails-plugins/mongodb/.settings/org.codehaus.groovy.eclipse.preferences.prefs b/grails-plugins/mongodb/.settings/org.codehaus.groovy.eclipse.preferences.prefs deleted file mode 100644 index bf339c7..0000000 --- a/grails-plugins/mongodb/.settings/org.codehaus.groovy.eclipse.preferences.prefs +++ /dev/null
@@ -1,3 +0,0 @@ -#Created by grails -eclipse.preferences.version=1 -groovy.dont.generate.class.files=true
diff --git a/grails-plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-plugins/mongodb/MongodbGrailsPlugin.groovy deleted file mode 100644 index 5941562..0000000 --- a/grails-plugins/mongodb/MongodbGrailsPlugin.groovy +++ /dev/null
@@ -1,84 +0,0 @@ - -import org.grails.datastore.gorm.mongo.plugin.support.MongoMethodsConfigurer -import org.grails.datastore.gorm.mongo.plugin.support.MongoOnChangeHandler -import org.grails.datastore.gorm.mongo.plugin.support.MongoSpringConfigurer -import grails.converters.* -import org.codehaus.groovy.grails.web.json.JSONWriter -import com.mongodb.* - - -class MongodbGrailsPlugin { - def license = "Apache 2.0 License" - def organization = [name: "SpringSource", url: "http://www.springsource.org/"] - def developers = [ - [name: "Graeme Rocher", email: "grocher@vmware.com"]] - def issueManagement = [system: "JIRA", url: "http://jira.grails.org/browse/GPMONGODB"] - def scm = [url: "https://github.com/grails/grails-data-mapping"] - - def version = "3.0.2" - def grailsVersion = "2.3.2 > *" - def observe = ['services', 'domainClass'] - def loadAfter = ['domainClass', 'hibernate', 'hibernate4', 'services', 'cloudFoundry'] - def author = "Graeme Rocher" - def authorEmail = "graeme.rocher@springsource.com" - def title = "MongoDB GORM" - def description = 'A plugin that integrates the Mongo document datastore into Grails, providing a GORM API onto it' - - def documentation = "http://grails.github.io/grails-data-mapping/mongodb" - - def doWithSpring = new MongoSpringConfigurer().getConfiguration() - - def doWithApplicationContext = { - JSON.registerObjectMarshaller DBObject, { dbo, json -> - JSONWriter writer = json.getWriter(); - - writer.object() - dbo.each { k, v -> - writer.key(k) - json.convertAnother(v) - } - writer.endObject() - - null - } - JSON.registerObjectMarshaller(BasicDBList, 999) { dbo, json -> - JSONWriter writer = json.getWriter(); - - writer.array(); - dbo.each { val -> json.convertAnother(val) } - writer.endArray(); - - null - } - - JSON.registerObjectMarshaller(BasicDBObject, 999) { dbo, json -> - JSONWriter writer = json.getWriter(); - - writer.object() - dbo.each { k, v -> - writer.key(k) - json.convertAnother(v) - } - writer.endObject() - - null - } - - } - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.mongoDatastore - def transactionManager = ctx.mongoTransactionManager - def methodsConfigurer = new MongoMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") || manager.hasGrailsPlugin("hibernate4") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - methodsConfigurer.configure() - } - - def onChange = { event -> - if(event.ctx) { - new MongoOnChangeHandler(event.ctx.mongoDatastore, event.ctx.mongoTransactionManager).onChange(delegate, event) - } - } -}
diff --git a/grails-plugins/mongodb/application.properties b/grails-plugins/mongodb/application.properties deleted file mode 100644 index 05fac38..0000000 --- a/grails-plugins/mongodb/application.properties +++ /dev/null
@@ -1 +0,0 @@ -app.grails.version=2.3.8
diff --git a/grails-plugins/mongodb/build.gradle b/grails-plugins/mongodb/build.gradle new file mode 100644 index 0000000..f6e47a0 --- /dev/null +++ b/grails-plugins/mongodb/build.gradle
@@ -0,0 +1,46 @@ + +group = "org.grails.plugins" +version = "4.0.0.BUILD-SNAPSHOT" + +apply from:'https://raw.githubusercontent.com/grails/grails-boot/master/gradle/maven-central-build.gradle' + +configurations { + provided +} + +dependencies { + + + provided("org.grails:grails-core:$grailsVersion") + provided("org.grails:grails-plugin-converters:$grailsVersion") + provided 'javax.servlet:javax.servlet-api:3.1.0' + compile 'org.codehaus.groovy:groovy:2.3.7' + + compile project(":grails-datastore-gorm-mongodb"), { + exclude group:'org.springframework', module:'spring-context' + exclude group:'org.springframework', module:'spring-core' + exclude group:'org.springframework', module:'spring-beans' + exclude group:'org.springframework', module:'spring-tx' + exclude group:'org.grails', module:'grails-bootstrap' + exclude group:'org.codehaus.groovy', module:'groovy-all' + exclude group:'org.grails', module:'grails-core' + exclude group:'org.grails', module:'grails-async' + exclude group:'javax.transaction', module:'jta' + } +} + +sourceSets { + main { + compileClasspath += configurations.provided + } + javadoc { + classpath = configurations.compile + configurations.provided + } +} + +def installer = install.repositories.mavenInstaller +def deployer = uploadArchives.repositories.mavenDeployer + +[installer, deployer]*.pom*.whenConfigured { pom -> + pom.artifactId = 'mongodb' +} \ No newline at end of file
diff --git a/grails-plugins/mongodb/grails-app/conf/Config.groovy b/grails-plugins/mongodb/grails-app/conf/Config.groovy deleted file mode 100644 index 2e57c6d..0000000 --- a/grails-plugins/mongodb/grails-app/conf/Config.groovy +++ /dev/null
@@ -1,24 +0,0 @@ -// configuration for plugin testing - will not be included in the plugin zip - -log4j = { - // Example of changing the log pattern for the default console - // appender: - // - //appenders { - // console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n') - //} - - error 'org.codehaus.groovy.grails.web.servlet', // controllers - 'org.codehaus.groovy.grails.web.pages', // GSP - 'org.codehaus.groovy.grails.web.sitemesh', // layouts - 'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping - 'org.codehaus.groovy.grails.web.mapping', // URL mapping - 'org.codehaus.groovy.grails.commons', // core / classloading - 'org.codehaus.groovy.grails.plugins', // plugins - 'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration - 'org.springframework', - 'org.hibernate', - 'net.sf.ehcache.hibernate' - - warn 'org.mortbay.log' -}
diff --git a/grails-plugins/mongodb/grails-app/conf/DataSource.groovy b/grails-plugins/mongodb/grails-app/conf/DataSource.groovy deleted file mode 100644 index 76bedde..0000000 --- a/grails-plugins/mongodb/grails-app/conf/DataSource.groovy +++ /dev/null
@@ -1,32 +0,0 @@ -dataSource { - pooled = true - driverClassName = "org.h2.Driver" - username = "sa" - password = "" -} -hibernate { - cache.use_second_level_cache = true - cache.use_query_cache = true - cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider' -} -// environment specific settings -environments { - development { - dataSource { - dbCreate = "create-drop" // one of 'create', 'create-drop','update' - url = "jdbc:h2:mem:devDB" - } - } - test { - dataSource { - dbCreate = "update" - url = "jdbc:h2:mem:testDb" - } - } - production { - dataSource { - dbCreate = "update" - url = "jdbc:h2:prodDb" - } - } -}
diff --git a/grails-plugins/mongodb/scripts/_Install.groovy b/grails-plugins/mongodb/scripts/_Install.groovy deleted file mode 100644 index a212160..0000000 --- a/grails-plugins/mongodb/scripts/_Install.groovy +++ /dev/null
@@ -1,10 +0,0 @@ -// -// This script is executed by Grails after plugin was installed to project. -// This script is a Gant script so you can use all special variables provided -// by Gant (such as 'baseDir' which points on project base dir). You can -// use 'ant' to access a global instance of AntBuilder -// -// For example you can create directory under project tree: -// -// ant.mkdir(dir:"${basedir}/grails-app/jobs") -//
diff --git a/grails-plugins/mongodb/scripts/_Uninstall.groovy b/grails-plugins/mongodb/scripts/_Uninstall.groovy deleted file mode 100644 index 7c53169..0000000 --- a/grails-plugins/mongodb/scripts/_Uninstall.groovy +++ /dev/null
@@ -1,5 +0,0 @@ -// -// This script is executed by Grails when the plugin is uninstalled from project. -// Use this script if you intend to do any additional clean-up on uninstall, but -// beware of messing up SVN directories! -//
diff --git a/grails-plugins/mongodb/scripts/_Upgrade.groovy b/grails-plugins/mongodb/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c9..0000000 --- a/grails-plugins/mongodb/scripts/_Upgrade.groovy +++ /dev/null
@@ -1,10 +0,0 @@ -// -// This script is executed by Grails during application upgrade ('grails upgrade' -// command). This script is a Gant script so you can use all special variables -// provided by Gant (such as 'baseDir' which points on project base dir). You can -// use 'ant' to access a global instance of AntBuilder -// -// For example you can create directory under project tree: -// -// ant.mkdir(dir:"${basedir}/grails-app/jobs") -//
diff --git a/grails-plugins/mongodb/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-plugins/mongodb/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy new file mode 100644 index 0000000..b623063 --- /dev/null +++ b/grails-plugins/mongodb/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy
@@ -0,0 +1,107 @@ +package grails.plugins.mongodb + +import com.mongodb.BasicDBList +import com.mongodb.BasicDBObject +import com.mongodb.DBObject +import grails.core.GrailsClass +import grails.mongodb.bootstrap.MongoDbDataStoreSpringInitializer +import grails.plugins.Plugin +import groovy.transform.CompileStatic +import org.grails.core.artefact.DomainClassArtefactHandler +import org.grails.datastore.gorm.mongo.plugin.support.MongoMethodsConfigurer +import org.grails.datastore.gorm.mongo.plugin.support.MongoOnChangeHandler +import org.grails.datastore.mapping.mongo.MongoDatastore +import org.grails.web.json.JSONWriter +import grails.converters.JSON +import org.springframework.beans.factory.support.BeanDefinitionRegistry +import org.springframework.transaction.PlatformTransactionManager + +class MongodbGrailsPlugin extends Plugin { + def license = "Apache 2.0 License" + def organization = [name: "SpringSource", url: "http://www.springsource.org/"] + def developers = [ + [name: "Graeme Rocher", email: "grocher@vmware.com"]] + def issueManagement = [system: "JIRA", url: "http://jira.grails.org/browse/GPMONGODB"] + def scm = [url: "https://github.com/grails/grails-data-mapping"] + + def version = "3.0.2" + def grailsVersion = "2.3.2 > *" + def observe = ['services', 'domainClass'] + def loadAfter = ['domainClass', 'hibernate', 'hibernate4', 'services', 'cloudFoundry'] + def author = "Graeme Rocher" + def authorEmail = "graeme.rocher@springsource.com" + def title = "MongoDB GORM" + def description = 'A plugin that integrates the Mongo document datastore into Grails, providing a GORM API onto it' + + def documentation = "http://grails.github.io/grails-data-mapping/mongodb" + + @Override + Closure doWithSpring() { + def initializer = new MongoDbDataStoreSpringInitializer(config, grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE).collect() { GrailsClass cls -> cls.clazz }) + initializer.registerApplicationIfNotPresent = false + return initializer.getBeanDefinitions((BeanDefinitionRegistry)applicationContext) + } + + @Override + void doWithApplicationContext() { + JSON.registerObjectMarshaller DBObject, { dbo, json -> + JSONWriter writer = json.getWriter(); + + writer.object() + dbo.each { k, v -> + writer.key(k) + json.convertAnother(v) + } + writer.endObject() + + null + } + JSON.registerObjectMarshaller(BasicDBList, 999) { dbo, json -> + JSONWriter writer = json.getWriter(); + + writer.array(); + dbo.each { val -> json.convertAnother(val) } + writer.endArray(); + + null + } + + JSON.registerObjectMarshaller(BasicDBObject, 999) { dbo, json -> + JSONWriter writer = json.getWriter(); + + writer.object() + dbo.each { k, v -> + writer.key(k) + json.convertAnother(v) + } + writer.endObject() + + null + } + } + + @Override + @CompileStatic + void doWithDynamicMethods() { + def ctx = applicationContext + def datastore = ctx.getBean(MongoDatastore) + def transactionManager = ctx.getBean('mongoTransactionManager', PlatformTransactionManager) + def methodsConfigurer = new MongoMethodsConfigurer(datastore, transactionManager) + methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") || manager.hasGrailsPlugin("hibernate4") + methodsConfigurer.failOnError = config.getProperty('grails.gorm.failOnError', Boolean, false) + methodsConfigurer.configure() + } + + @Override + @CompileStatic + void onChange(Map<String, Object> event) { + + def ctx = applicationContext + event.application = grailsApplication + event.ctx = applicationContext + + def mongoDatastore = ctx.getBean(MongoDatastore) + def mongoTransactionManager = ctx.getBean('mongoTransactionManager', PlatformTransactionManager) + new MongoOnChangeHandler(mongoDatastore, mongoTransactionManager).onChange(this, event) + } +}
diff --git a/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy b/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy index a5257e2..8191619 100644 --- a/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy +++ b/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy
@@ -5,7 +5,7 @@ grails.project.dependency.resolution = { inherits("global") { - excludes 'xml-apis', 'netty'//, 'xercesImpl' + excludes 'xml-apis', 'netty', 'logback-classic' //, 'xercesImpl' } log "warn" checksums true @@ -63,6 +63,7 @@ } test "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" test "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" + test "org.spockframework:spock-grails-support:0.7-groovy-2.0" // htmlunit seems to be broken /* test("org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion") {
diff --git a/grails-plugins/neo4j/test/integration/org/grails/datastore/gorm/neo4j/GetOrSetSpec.groovy b/grails-plugins/neo4j/test/integration/org/grails/datastore/gorm/neo4j/GetOrSetSpec.groovy index 9fcaec6..4505ad6 100644 --- a/grails-plugins/neo4j/test/integration/org/grails/datastore/gorm/neo4j/GetOrSetSpec.groovy +++ b/grails-plugins/neo4j/test/integration/org/grails/datastore/gorm/neo4j/GetOrSetSpec.groovy
@@ -5,10 +5,20 @@ import org.codehaus.groovy.grails.web.json.JSONElement import org.neo4j.graphdb.DynamicRelationshipType import org.neo4j.graphdb.GraphDatabaseService +import org.neo4j.graphdb.Transaction class GetOrSetSpec extends IntegrationSpec { GraphDatabaseService graphDatabaseService + Transaction tx + + def setup() { + tx = graphDatabaseService.beginTx() + } + + def cleanup() { + tx.close() + } def "test getOrSet method on nodes"() { setup: @@ -66,4 +76,7 @@ (object as JSON).render(sw) JSON.parse(sw.toString()) } + + + }
diff --git a/settings.gradle b/settings.gradle index 4aa0322..6035621 100644 --- a/settings.gradle +++ b/settings.gradle
@@ -1,7 +1,7 @@ // Datastore Project include ("grails-datastore-core", "grails-datastore-gemfire", - "grails-datastore-jpa", +// "grails-datastore-jpa", /* "grails-datastore-riak",*/ "grails-datastore-simple", "grails-datastore-web", @@ -34,6 +34,8 @@ 'grails-plugins:redis', 'grails-plugins:riak', */ + 'grails-plugins/hibernate', + 'grails-plugins/mongodb', // Boot Extensions // 'boot-plugins/gorm-hibernate4-spring-boot', @@ -41,7 +43,7 @@ // GORM Implementations 'grails-datastore-gorm-cassandra', - 'grails-datastore-gorm-jpa', +// 'grails-datastore-gorm-jpa', 'grails-datastore-gorm-neo4j', 'grails-datastore-gorm-redis', 'grails-datastore-gorm-rest-client',